@agent-native/core 0.22.22 → 0.22.23
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/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +6 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +39 -3
- package/dist/extensions/actions.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +5 -1
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +39 -4
- package/dist/server/framework-request-handler.js.map +1 -1
- package/docs/content/dispatch.md +13 -3
- package/docs/content/external-agents.md +41 -67
- package/docs/content/mcp-protocol.md +3 -3
- package/docs/content/template-dispatch.md +6 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework-request-handler.d.ts","sourceRoot":"","sources":["../../src/server/framework-request-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,IAAI,CAAC;AAMhD,QAAA,MAAM,gBAAgB,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"framework-request-handler.d.ts","sourceRoot":"","sources":["../../src/server/framework-request-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,YAAY,EAAW,MAAM,IAAI,CAAC;AAMhD,QAAA,MAAM,gBAAgB,mBAAmB,CAAC;AAwD1C;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/C,GAAG,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAQ3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,CAqDjD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjE;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,EACtB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACjC,IAAI,CA0BN;AAmCD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,GAAG,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAqBf;AAwSD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC,CAyBd;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -7,6 +7,7 @@ const WELL_KNOWN_PREFIX = "/.well-known";
|
|
|
7
7
|
const APP_SHIM_KEY = "_agentNativeH3Shim";
|
|
8
8
|
const BOOTSTRAP_PROMISE_KEY = "_agentNativeBootstrapPromise";
|
|
9
9
|
const PLUGIN_READY_KEY = "_agentNativePluginReadyPromise";
|
|
10
|
+
const PLUGIN_READY_PLACEHOLDERS_KEY = "_agentNativePluginReadyPlaceholders";
|
|
10
11
|
const PROVIDED_PLUGIN_STEMS_KEY = "_agentNativeProvidedPluginStems";
|
|
11
12
|
function normalizeAppBasePath(value) {
|
|
12
13
|
if (!value || value === "/")
|
|
@@ -101,8 +102,12 @@ export function getH3App(nitroApp) {
|
|
|
101
102
|
// Fall through — the actual route handler runs next.
|
|
102
103
|
return undefined;
|
|
103
104
|
});
|
|
104
|
-
registerMiddleware(nitroApp, FRAMEWORK_PREFIX, readinessGate
|
|
105
|
-
|
|
105
|
+
registerMiddleware(nitroApp, FRAMEWORK_PREFIX, readinessGate, {
|
|
106
|
+
prepend: true,
|
|
107
|
+
});
|
|
108
|
+
registerMiddleware(nitroApp, WELL_KNOWN_PREFIX, readinessGate, {
|
|
109
|
+
prepend: true,
|
|
110
|
+
});
|
|
106
111
|
}
|
|
107
112
|
return shim;
|
|
108
113
|
}
|
|
@@ -154,6 +159,10 @@ async function awaitFrameworkRoutesReadyForRequest(nitroApp, reqPath) {
|
|
|
154
159
|
export function trackPluginInit(nitroApp, promise, options = {}) {
|
|
155
160
|
if (!nitroApp)
|
|
156
161
|
return;
|
|
162
|
+
// Ensure the readiness gate exists even when the tracked plugin is the first
|
|
163
|
+
// framework code to run in a serverless isolate. Otherwise an immediate
|
|
164
|
+
// first request can fall through before the plugin registers its routes.
|
|
165
|
+
getH3App(nitroApp);
|
|
157
166
|
// Attach a no-op catch so the promise doesn't surface as an unhandled
|
|
158
167
|
// rejection when Nitro v3 drops the async return value. The actual error
|
|
159
168
|
// is still observable when awaitPluginsReady() re-awaits the promise.
|
|
@@ -171,6 +180,27 @@ export function trackPluginInit(nitroApp, promise, options = {}) {
|
|
|
171
180
|
else {
|
|
172
181
|
nitroApp[PLUGIN_READY_KEY] = [entry];
|
|
173
182
|
}
|
|
183
|
+
installPluginReadyPlaceholders(nitroApp, entry.paths);
|
|
184
|
+
}
|
|
185
|
+
function installPluginReadyPlaceholders(nitroApp, paths) {
|
|
186
|
+
if (!paths?.length)
|
|
187
|
+
return;
|
|
188
|
+
const existing = nitroApp[PLUGIN_READY_PLACEHOLDERS_KEY];
|
|
189
|
+
const installed = existing ?? new Set();
|
|
190
|
+
nitroApp[PLUGIN_READY_PLACEHOLDERS_KEY] = installed;
|
|
191
|
+
const app = getH3App(nitroApp);
|
|
192
|
+
for (const path of paths) {
|
|
193
|
+
if (!path || installed.has(path))
|
|
194
|
+
continue;
|
|
195
|
+
installed.add(path);
|
|
196
|
+
registerMiddleware(nitroApp, path, (async (event) => {
|
|
197
|
+
const eventAny = event;
|
|
198
|
+
await awaitFrameworkRoutesReadyForRequest(nitroApp, eventAny.context?._mountedPathname ?? event.url?.pathname ?? path);
|
|
199
|
+
return undefined;
|
|
200
|
+
}), {
|
|
201
|
+
prepend: true,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
174
204
|
}
|
|
175
205
|
/**
|
|
176
206
|
* Await all tracked plugin initializations. Called by the readiness gate
|
|
@@ -204,7 +234,7 @@ export async function awaitPluginsReady(nitroApp, reqPath) {
|
|
|
204
234
|
* - Exact-match prefix: `/foo` matches `/foo`, `/foo/bar`, but not `/foobar`
|
|
205
235
|
* - Empty path: middleware runs on every request
|
|
206
236
|
*/
|
|
207
|
-
function registerMiddleware(nitroApp, path, handler) {
|
|
237
|
+
function registerMiddleware(nitroApp, path, handler, options = {}) {
|
|
208
238
|
const h3 = nitroApp.h3;
|
|
209
239
|
if (!h3 || !Array.isArray(h3["~middleware"])) {
|
|
210
240
|
throw new Error("[agent-native] Cannot register route: nitroApp.h3 is not available. " +
|
|
@@ -354,7 +384,12 @@ function registerMiddleware(nitroApp, path, handler) {
|
|
|
354
384
|
restoreOriginalPath();
|
|
355
385
|
}
|
|
356
386
|
};
|
|
357
|
-
|
|
387
|
+
if (options.prepend) {
|
|
388
|
+
h3["~middleware"].unshift(middleware);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
h3["~middleware"].push(middleware);
|
|
392
|
+
}
|
|
358
393
|
}
|
|
359
394
|
/**
|
|
360
395
|
* Auto-mount any default framework plugins that the template doesn't provide.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework-request-handler.js","sourceRoot":"","sources":["../../src/server/framework-request-handler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Framework request handler — registers framework routes on Nitro's h3 instance.\n *\n * Nitro 3 exposes its h3 app as `nitroApp.h3`. We register framework routes\n * directly on it as middleware (`nitroApp.h3[\"~middleware\"]`), giving each\n * plugin a path-prefix-matched handler that runs before any file-based route.\n *\n * Plugins call `getH3App(nitroApp).use(path, handler)` exactly like h3 v1's\n * `app.use()` — the wrapper translates that into v2 middleware registration.\n *\n * Default plugins that the template doesn't provide are auto-mounted on the\n * first call to `getH3App()` per nitroApp instance.\n */\nimport type { EventHandler, H3Event } from \"h3\";\nimport { setResponseHeader, setResponseStatus } from \"h3\";\nimport { getMissingDefaultPlugins } from \"../deploy/route-discovery.js\";\n\nconst BOOTSTRAPPED = new WeakSet<object>();\nconst IN_BOOTSTRAP = new WeakSet<object>();\nconst FRAMEWORK_PREFIX = \"/_agent-native\";\nconst WELL_KNOWN_PREFIX = \"/.well-known\";\nconst APP_SHIM_KEY = \"_agentNativeH3Shim\";\nconst BOOTSTRAP_PROMISE_KEY = \"_agentNativeBootstrapPromise\";\nconst PLUGIN_READY_KEY = \"_agentNativePluginReadyPromise\";\nconst PROVIDED_PLUGIN_STEMS_KEY = \"_agentNativeProvidedPluginStems\";\n\ninterface PluginReadyEntry {\n promise: Promise<void>;\n paths?: string[];\n}\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n}\n\nfunction pathMatchesPrefix(reqPath: string, prefix: string): boolean {\n return reqPath === prefix || reqPath.startsWith(prefix + \"/\");\n}\n\nfunction supportsAppBasePathMount(path: string): boolean {\n return (\n pathMatchesPrefix(path, FRAMEWORK_PREFIX) ||\n pathMatchesPrefix(path, WELL_KNOWN_PREFIX)\n );\n}\n\nfunction resolveMountMatch(\n reqPath: string,\n path: string,\n): { mountPath: string; strippedPath: string } | null {\n if (pathMatchesPrefix(reqPath, path)) {\n return { mountPath: path, strippedPath: reqPath.slice(path.length) || \"/\" };\n }\n\n const appBasePath = getAppBasePath();\n if (!appBasePath || !supportsAppBasePathMount(path)) return null;\n\n const prefixedPath = `${appBasePath}${path}`;\n if (!pathMatchesPrefix(reqPath, prefixedPath)) return null;\n return {\n mountPath: prefixedPath,\n strippedPath: reqPath.slice(prefixedPath.length) || \"/\",\n };\n}\n\n/**\n * Wrapper around Nitro's h3 instance that exposes a v1-style `.use()` API\n * for registering path-prefix middleware.\n */\nexport interface H3AppShim {\n use(path: string, handler: EventHandler): void;\n use(handler: EventHandler): void;\n}\n\n/**\n * Mark a default plugin slot as supplied by the app/template before the\n * framework default bootstrap runs.\n *\n * Bundled serverless functions often don't have the original\n * `server/plugins/*.ts` tree on disk at runtime, so filesystem route discovery\n * can falsely conclude a template plugin is missing. Explicit plugin factories\n * call this synchronously before awaiting bootstrap so the framework does not\n * auto-mount a generic default over the app's custom implementation.\n */\nexport function markDefaultPluginProvided(nitroApp: any, stem: string): void {\n if (!nitroApp || !stem) return;\n const existing = nitroApp[PROVIDED_PLUGIN_STEMS_KEY] as\n | Set<string>\n | undefined;\n const provided = existing ?? new Set<string>();\n provided.add(stem);\n nitroApp[PROVIDED_PLUGIN_STEMS_KEY] = provided;\n}\n\n/**\n * Get (or create) the shared H3 app wrapper for a nitroApp. Plugins use this\n * to register routes via `.use(path, handler)`.\n *\n * On the first call per nitroApp, we kick off auto-mounting any missing\n * default plugins. User-facing plugin factories (createAgentChatPlugin,\n * createAuthPlugin, etc.) await this bootstrap via `awaitBootstrap()` so the\n * default plugins finish registering middleware before requests arrive.\n */\nexport function getH3App(nitroApp: any): H3AppShim {\n if (!nitroApp) throw new Error(\"getH3App: nitroApp is required\");\n\n // Reuse the cached shim if we've wrapped this nitroApp before\n const cached = nitroApp[APP_SHIM_KEY] as H3AppShim | undefined;\n if (cached) return cached;\n\n const shim: H3AppShim = {\n use(arg1: string | EventHandler, arg2?: EventHandler) {\n const path = typeof arg1 === \"string\" ? arg1 : \"\";\n const handler = (typeof arg1 === \"string\" ? arg2 : arg1) as EventHandler;\n if (typeof handler !== \"function\") {\n throw new Error(\"getH3App.use: handler must be a function\");\n }\n registerMiddleware(nitroApp, path, handler);\n },\n };\n\n nitroApp[APP_SHIM_KEY] = shim;\n\n if (!BOOTSTRAPPED.has(nitroApp)) {\n BOOTSTRAPPED.add(nitroApp);\n nitroApp[BOOTSTRAP_PROMISE_KEY] = bootstrapDefaultPlugins(nitroApp).catch(\n (err) => {\n console.warn(\n \"[agent-native] Failed to auto-mount default plugins:\",\n (err as Error).message,\n );\n },\n );\n\n // Readiness gate: Nitro v3 doesn't await async plugins, so routes\n // registered inside an async plugin may not exist when the first\n // request arrives. These middleware entries hold framework routes\n // until default-plugin bootstrap and tracked plugin inits complete.\n const readinessGate = (async (event: H3Event) => {\n const eventAny = event as any;\n await awaitFrameworkRoutesReadyForRequest(\n nitroApp,\n eventAny.context?._mountedPathname ?? event.url?.pathname ?? \"\",\n );\n // Fall through — the actual route handler runs next.\n return undefined;\n }) as EventHandler;\n registerMiddleware(nitroApp, FRAMEWORK_PREFIX, readinessGate);\n registerMiddleware(nitroApp, WELL_KNOWN_PREFIX, readinessGate);\n }\n\n return shim;\n}\n\n/**\n * Wait for the framework's default-plugin bootstrap to complete.\n *\n * Called by user-facing plugin factories (`createAgentChatPlugin`, etc.) at\n * the top of their plugin function, so that by the time the function returns\n * — and Nitro starts accepting requests — all default plugins have finished\n * registering their middleware.\n *\n * No-op when called from inside the bootstrap itself (avoids deadlock when a\n * default plugin happens to be running as part of bootstrap).\n */\nexport async function awaitBootstrap(nitroApp: any): Promise<void> {\n if (!nitroApp || IN_BOOTSTRAP.has(nitroApp)) return;\n // Trigger bootstrap if it hasn't been already (idempotent — getH3App\n // creates the shim and kicks off bootstrap on first call).\n getH3App(nitroApp);\n const promise = nitroApp[BOOTSTRAP_PROMISE_KEY];\n if (promise) await promise;\n}\n\n/**\n * Wait until framework routes are safe to dispatch.\n *\n * Request-time gates must wait for both phases:\n * 1. default-plugin bootstrap, which discovers and starts missing plugins\n * 2. async plugin init promises, which register routes such as A2A cards\n */\nasync function awaitFrameworkRoutesReadyForRequest(\n nitroApp: any,\n reqPath: string,\n): Promise<void> {\n if (!nitroApp) return;\n const bootstrapPromise = nitroApp[BOOTSTRAP_PROMISE_KEY];\n if (bootstrapPromise) await bootstrapPromise;\n await awaitPluginsReady(nitroApp, reqPath);\n}\n\n/**\n * Track an async plugin's initialization promise. Nitro v3 calls plugins\n * synchronously and doesn't await async return values, so routes registered\n * inside an async plugin may not be ready when the first request arrives.\n *\n * Call this from the TOP of any async plugin so that the readiness gate\n * (installed by getH3App) can hold /_agent-native requests until the plugin\n * finishes mounting its routes.\n */\nexport function trackPluginInit(\n nitroApp: any,\n promise: Promise<void>,\n options: { paths?: string[] } = {},\n): void {\n if (!nitroApp) return;\n // Attach a no-op catch so the promise doesn't surface as an unhandled\n // rejection when Nitro v3 drops the async return value. The actual error\n // is still observable when awaitPluginsReady() re-awaits the promise.\n const safe = promise.catch((err) => {\n console.error(\n \"[agent-native] Plugin init failed:\",\n (err as Error).message || err,\n );\n });\n const entry: PluginReadyEntry = {\n promise: safe,\n paths: options.paths?.filter(Boolean),\n };\n const existing = nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined;\n if (existing) {\n existing.push(entry);\n } else {\n nitroApp[PLUGIN_READY_KEY] = [entry];\n }\n}\n\n/**\n * Await all tracked plugin initializations. Called by the readiness gate\n * middleware before dispatching framework routes.\n */\nexport async function awaitPluginsReady(\n nitroApp: any,\n reqPath?: string,\n): Promise<void> {\n const entries = nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined;\n if (!entries?.length) return;\n\n const relevant = reqPath\n ? entries.filter((entry) =>\n entry.paths?.length\n ? entry.paths.some((path) => resolveMountMatch(reqPath, path))\n : true,\n )\n : entries;\n\n if (relevant.length) {\n await Promise.all(relevant.map((entry) => entry.promise));\n const completed = new Set(relevant);\n const latest =\n (nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined) ?? [];\n nitroApp[PLUGIN_READY_KEY] = latest.filter(\n (entry) => !completed.has(entry),\n );\n }\n}\n\n/**\n * Register a path-prefix middleware on Nitro's h3 instance.\n *\n * The middleware:\n * - Returns `next()` (continues) if the request path doesn't match.\n * - Otherwise dispatches to the handler. If the handler returns a value,\n * it short-circuits the request. If it returns undefined, next() runs.\n *\n * Path matching emulates h3 v1's `app.use(path, ...)` behavior:\n * - Exact-match prefix: `/foo` matches `/foo`, `/foo/bar`, but not `/foobar`\n * - Empty path: middleware runs on every request\n */\nfunction registerMiddleware(\n nitroApp: any,\n path: string,\n handler: EventHandler,\n) {\n const h3 = nitroApp.h3;\n if (!h3 || !Array.isArray(h3[\"~middleware\"])) {\n throw new Error(\n \"[agent-native] Cannot register route: nitroApp.h3 is not available. \" +\n \"Make sure you're calling getH3App() from inside a Nitro plugin.\",\n );\n }\n\n const middleware = async (event: H3Event, next: () => any) => {\n let originalPathname: string | undefined;\n let originalEventPath: string | undefined;\n let hadEventPath = false;\n const restoreOriginalPath = () => {\n if (originalPathname !== undefined) {\n try {\n event.url.pathname = originalPathname;\n } catch {\n // ignore\n }\n originalPathname = undefined;\n }\n if (hadEventPath) {\n try {\n (event as any).path = originalEventPath;\n } catch {\n // ignore\n }\n } else {\n try {\n delete (event as any).path;\n } catch {\n // ignore\n }\n }\n };\n if (path) {\n const reqPath = event.url?.pathname ?? \"\";\n const match = resolveMountMatch(reqPath, path);\n if (!match) {\n return next();\n }\n // Strip the mount prefix from event.url.pathname so handlers that\n // dispatch sub-routes can read `event.path` (or `event.url.pathname`)\n // and see the path RELATIVE to their mount point — matching h3 v1's\n // `app.use(path, handler)` semantics.\n const eventAny = event as any;\n hadEventPath = \"path\" in eventAny;\n originalEventPath = eventAny.path;\n try {\n originalPathname = event.url.pathname;\n // Save the full path in context so handlers that need the original URL\n // (e.g. Better Auth, which extracts its own basePath prefix) can\n // reconstruct a Request with the un-stripped URL.\n eventAny.context = eventAny.context ?? {};\n eventAny.context._mountedPathname = originalPathname;\n eventAny.context._mountPrefix = match.mountPath;\n event.url.pathname = match.strippedPath;\n eventAny.path = `${match.strippedPath}${event.url.search || \"\"}`;\n } catch {\n // event.url is read-only on some runtimes — fall through. Handlers\n // that don't depend on prefix stripping (most of them) still work.\n }\n }\n try {\n const result = await handler(event);\n if (result === undefined) {\n // Restore the original pathname BEFORE calling next() so downstream\n // middleware sees the full URL — not the stripped mount-relative path.\n // Matches h3 v2's own sub-app middleware pattern where the restore\n // happens inside the next() callback, not after it returns.\n restoreOriginalPath();\n return next();\n }\n return result;\n } catch (err) {\n // Log 500s to the server console so they're debuggable, and respond\n // with JSON instead of the default HTML error page so clients can\n // surface error messages. This only applies to routes mounted under\n // the framework prefix (or middleware mounted at `/`, for which we\n // still want visibility).\n const reqPath = originalPathname ?? event.url?.pathname ?? \"\";\n const e = err as any;\n const status =\n typeof e?.statusCode === \"number\"\n ? e.statusCode\n : typeof e?.status === \"number\"\n ? e.status\n : 500;\n console.error(\n `[agent-native] ${event.method ?? \"\"} ${reqPath} failed (${status}):`,\n e?.stack || e?.message || e,\n );\n // Forward 5xx to server-side Sentry — Nitro's own `error` hook may not\n // fire here because we convert the throw into a normal JSON response,\n // and a console.error alone is invisible in deployed environments.\n // 4xx are user-input errors (validation, auth) and aren't worth\n // alerting on. Lazy-loaded so the framework-request-handler module\n // doesn't pull @sentry/node into bundles that don't need it.\n if (status >= 500) {\n // Static `import` would create a cycle (sentry.ts imports auth.ts\n // which imports… eventually, framework-request-handler.ts).\n import(\"./sentry.js\")\n .then(({ captureRouteError, isServerSentryEnabled }) => {\n if (!isServerSentryEnabled()) return;\n captureRouteError(err, {\n route: reqPath,\n method: event.method,\n userAgent: (() => {\n try {\n return event.headers?.get(\"user-agent\") ?? undefined;\n } catch {\n return undefined;\n }\n })(),\n });\n })\n .catch(() => {\n // Sentry is observability — never let it break a response path.\n });\n }\n try {\n setResponseStatus(event, status);\n setResponseHeader(event, \"content-type\", \"application/json\");\n } catch {\n // Response already sent — best effort.\n }\n return {\n error: e?.message || \"Internal server error\",\n // Only surface the stack to clients when explicitly enabled.\n // `NODE_ENV !== \"production\"` was unsafe — preview deploys and\n // any host that forgets to set NODE_ENV=production leaked stack\n // traces (file paths, dependency versions, internal route\n // topology) to anonymous callers. Operators who want stacks in\n // dev set `AGENT_NATIVE_DEBUG_ERRORS=1` explicitly.\n ...(status >= 500 &&\n process.env.AGENT_NATIVE_DEBUG_ERRORS === \"1\" &&\n e?.stack\n ? { stack: e.stack }\n : {}),\n };\n } finally {\n // Restore the original pathname so downstream middleware sees the\n // full URL.\n restoreOriginalPath();\n }\n };\n\n h3[\"~middleware\"].push(middleware);\n}\n\n/**\n * Auto-mount any default framework plugins that the template doesn't provide.\n *\n * Runs once per nitroApp on the first `getH3App()` call. Uses route-discovery\n * to find which default plugin stems are missing from `server/plugins/`, then\n * dynamically imports and mounts them. If a workspace core is present in the\n * ancestor chain, plugin slots the workspace core exports are mounted from\n * there instead of from @agent-native/core — this is the middle layer of the\n * three-layer inheritance model (app local > workspace core > framework).\n */\nasync function bootstrapDefaultPlugins(nitroApp: any): Promise<void> {\n IN_BOOTSTRAP.add(nitroApp);\n try {\n const cwd = process.cwd();\n const discoveredMissing = await getMissingDefaultPlugins(cwd);\n const provided = nitroApp[PROVIDED_PLUGIN_STEMS_KEY] as\n | Set<string>\n | undefined;\n const missing = provided\n ? discoveredMissing.filter((stem) => !provided.has(stem))\n : discoveredMissing;\n if (missing.length === 0) return;\n\n // Lazy import to avoid circular dependency at module load time\n const serverModule = await import(\"./index.js\");\n const terminalModule = await import(\"../terminal/terminal-plugin.js\");\n const integrationsModule = await import(\"../integrations/plugin.js\");\n const orgModule = await import(\"../org/plugin.js\");\n const onboardingModule = await import(\"../onboarding/plugin.js\");\n\n const frameworkImpls: Record<\n string,\n ((nitroApp: any) => void | Promise<void>) | undefined\n > = {\n \"agent-chat\": (serverModule as any).defaultAgentChatPlugin,\n auth: (serverModule as any).defaultAuthPlugin,\n \"core-routes\": (serverModule as any).defaultCoreRoutesPlugin,\n integrations: (integrationsModule as any).defaultIntegrationsPlugin,\n onboarding: (onboardingModule as any).defaultOnboardingPlugin,\n org: (orgModule as any).defaultOrgPlugin,\n resources: (serverModule as any).defaultResourcesPlugin,\n sentry: (serverModule as any).defaultSentryPlugin,\n terminal: (terminalModule as any).defaultTerminalPlugin,\n };\n\n // Workspace core layer: if the app is inside an enterprise monorepo with\n // `agent-native.workspaceCore` configured, pull in any plugin slots the\n // workspace core exports from its server entry. We dynamically import the\n // workspace core package at runtime.\n let workspaceImpls: Record<\n string,\n ((nitroApp: any) => void | Promise<void>) | undefined\n > = {};\n try {\n const { getWorkspaceCoreExports } =\n await import(\"../deploy/workspace-core.js\");\n const ws = await getWorkspaceCoreExports(cwd);\n if (ws && Object.keys(ws.plugins).length > 0) {\n try {\n const wsServerModule = await loadWorkspaceCoreServer(\n ws.packageName,\n ws.packageDir,\n );\n for (const [slot, exportName] of Object.entries(ws.plugins)) {\n if (!exportName) continue;\n const impl = (wsServerModule as any)[exportName];\n if (typeof impl === \"function\") {\n workspaceImpls[slot] = impl;\n }\n }\n if (process.env.DEBUG) {\n console.log(\n `[agent-native] Workspace core ${ws.packageName} provides plugin slots: ${Object.keys(workspaceImpls).join(\", \")}`,\n );\n }\n } catch (e) {\n const msg = (e as Error).message ?? \"\";\n // Common cause: workspace-core's package.json points \"./server\"\n // at a TS source file (the scaffold default), but Node can't\n // resolve relative `.js` imports inside it without a TS loader.\n // Tell the user to compile to dist/ rather than just dumping the\n // raw resolution error.\n const tsLoadHint = /\\.js' imported from .*\\.ts/.test(msg)\n ? \" — workspace-core src is TypeScript but isn't being compiled. \" +\n \"Run `pnpm --filter \" +\n ws.packageName +\n \" build` and point its `./server` export at dist/server/index.js.\"\n : \"\";\n console.warn(\n `[agent-native] Failed to load workspace core ${ws.packageName}/server: ${msg}${tsLoadHint}`,\n );\n }\n }\n } catch {\n // Workspace shared package isn't available (e.g. running on an edge\n // runtime without fs). Silently fall through to framework defaults.\n }\n\n if (process.env.DEBUG)\n console.log(\n `[agent-native] Auto-mounting ${missing.length} default plugin(s): ${missing.join(\", \")}`,\n );\n\n for (const stem of missing) {\n // Prefer workspace-core impl over framework default when both exist.\n const impl = workspaceImpls[stem] ?? frameworkImpls[stem];\n if (typeof impl === \"function\") {\n try {\n await impl(nitroApp);\n } catch (e) {\n console.warn(\n `[agent-native] Failed to auto-mount default plugin ${stem}:`,\n (e as Error).message,\n );\n }\n }\n }\n } finally {\n IN_BOOTSTRAP.delete(nitroApp);\n }\n}\n\n/**\n * Load a workspace-core's `/server` entry, transparently handling TS source.\n *\n * The scaffolded workspace-core template ships TS sources without a build\n * step (exports point at `./src/server/index.ts`), so plain `await import()`\n * blows up the moment Node hits a relative `.js` import inside (the standard\n * TS ESM convention) — and even before that, Node may resolve the package\n * relative to the framework's own location rather than the user's monorepo.\n *\n * We try Node's plain `import()` first (fastest path when the user has\n * compiled to dist/) and fall through to jiti on any error. jiti is anchored\n * to a real file inside the workspace-core's directory, so its module\n * resolution starts in the right node_modules tree (handles pnpm hoisting\n * and linked workspaces) AND handles TS source files + `.js` → `.ts` ESM\n * extension remapping.\n *\n * Edge runtimes without `fs` won't be able to load jiti at all; the outer\n * try/catch silently falls through to framework defaults in that case.\n */\nexport async function loadWorkspaceCoreServer(\n packageName: string,\n packageDir: string,\n): Promise<any> {\n let firstErr: unknown;\n try {\n return await import(/* @vite-ignore */ `${packageName}/server`);\n } catch (e) {\n firstErr = e;\n }\n\n try {\n const { createJiti } = await import(\"jiti\");\n const { pathToFileURL } = await import(\"node:url\");\n const path = await import(\"node:path\");\n // Anchor jiti to a real file inside the workspace-core package so its\n // module resolution starts in the right node_modules tree (handles pnpm\n // hoisting and linked workspaces).\n const anchor = pathToFileURL(\n path.join(packageDir, \"package.json\"),\n ).toString();\n const jiti = createJiti(anchor, { interopDefault: true });\n return await jiti.import(`${packageName}/server`);\n } catch (jitiErr) {\n // jiti also failed — rethrow the original Node error since it's usually\n // more informative about *why* the package wasn't resolvable.\n throw firstErr ?? jitiErr;\n }\n}\n\nexport { FRAMEWORK_PREFIX };\n"]}
|
|
1
|
+
{"version":3,"file":"framework-request-handler.js","sourceRoot":"","sources":["../../src/server/framework-request-handler.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,YAAY,GAAG,IAAI,OAAO,EAAU,CAAC;AAC3C,MAAM,YAAY,GAAG,IAAI,OAAO,EAAU,CAAC;AAC3C,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAC1C,MAAM,iBAAiB,GAAG,cAAc,CAAC;AACzC,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAC1C,MAAM,qBAAqB,GAAG,8BAA8B,CAAC;AAC7D,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AAC1D,MAAM,6BAA6B,GAAG,qCAAqC,CAAC;AAC5E,MAAM,yBAAyB,GAAG,iCAAiC,CAAC;AAOpE,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IAC3C,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AAC/D,CAAC;AAED,SAAS,cAAc;IACrB,OAAO,oBAAoB,CACzB,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAC5D,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,MAAc;IACxD,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAY;IAC5C,OAAO,CACL,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,CAAC;QACzC,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,OAAe,EACf,IAAY;IAEZ,IAAI,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,IAAI,CAAC,WAAW,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEjE,MAAM,YAAY,GAAG,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,OAAO;QACL,SAAS,EAAE,YAAY;QACvB,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,GAAG;KACxD,CAAC;AACJ,CAAC;AAWD;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAa,EAAE,IAAY;IACnE,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI;QAAE,OAAO;IAC/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,yBAAyB,CAEtC,CAAC;IACd,MAAM,QAAQ,GAAG,QAAQ,IAAI,IAAI,GAAG,EAAU,CAAC;IAC/C,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,yBAAyB,CAAC,GAAG,QAAQ,CAAC;AACjD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAa;IACpC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAEjE,8DAA8D;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAA0B,CAAC;IAC/D,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,IAAI,GAAc;QACtB,GAAG,CAAC,IAA2B,EAAE,IAAmB;YAClD,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAiB,CAAC;YACzE,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;YAC9D,CAAC;YACD,kBAAkB,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;KACF,CAAC;IAEF,QAAQ,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IAE9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3B,QAAQ,CAAC,qBAAqB,CAAC,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC,KAAK,CACvE,CAAC,GAAG,EAAE,EAAE;YACN,OAAO,CAAC,IAAI,CACV,sDAAsD,EACrD,GAAa,CAAC,OAAO,CACvB,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,kEAAkE;QAClE,iEAAiE;QACjE,kEAAkE;QAClE,oEAAoE;QACpE,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;YAC9C,MAAM,QAAQ,GAAG,KAAY,CAAC;YAC9B,MAAM,mCAAmC,CACvC,QAAQ,EACR,QAAQ,CAAC,OAAO,EAAE,gBAAgB,IAAI,KAAK,CAAC,GAAG,EAAE,QAAQ,IAAI,EAAE,CAChE,CAAC;YACF,qDAAqD;YACrD,OAAO,SAAS,CAAC;QACnB,CAAC,CAAiB,CAAC;QACnB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE;YAC5D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE;YAC7D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAa;IAChD,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO;IACpD,qEAAqE;IACrE,2DAA2D;IAC3D,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnB,MAAM,OAAO,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAChD,IAAI,OAAO;QAAE,MAAM,OAAO,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,mCAAmC,CAChD,QAAa,EACb,OAAe;IAEf,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,MAAM,gBAAgB,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IACzD,IAAI,gBAAgB;QAAE,MAAM,gBAAgB,CAAC;IAC7C,MAAM,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAa,EACb,OAAsB,EACtB,UAAgC,EAAE;IAElC,IAAI,CAAC,QAAQ;QAAE,OAAO;IACtB,6EAA6E;IAC7E,wEAAwE;IACxE,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnB,sEAAsE;IACtE,yEAAyE;IACzE,sEAAsE;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,OAAO,CAAC,KAAK,CACX,oCAAoC,EACnC,GAAa,CAAC,OAAO,IAAI,GAAG,CAC9B,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAqB;QAC9B,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;KACtC,CAAC;IACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAmC,CAAC;IAC9E,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,8BAA8B,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,8BAA8B,CACrC,QAAa,EACb,KAA2B;IAE3B,IAAI,CAAC,KAAK,EAAE,MAAM;QAAE,OAAO;IAC3B,MAAM,QAAQ,GAAG,QAAQ,CAAC,6BAA6B,CAE1C,CAAC;IACd,MAAM,SAAS,GAAG,QAAQ,IAAI,IAAI,GAAG,EAAU,CAAC;IAChD,QAAQ,CAAC,6BAA6B,CAAC,GAAG,SAAS,CAAC;IAEpD,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC3C,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,kBAAkB,CAChB,QAAQ,EACR,IAAI,EACJ,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;YACxB,MAAM,QAAQ,GAAG,KAAY,CAAC;YAC9B,MAAM,mCAAmC,CACvC,QAAQ,EACR,QAAQ,CAAC,OAAO,EAAE,gBAAgB,IAAI,KAAK,CAAC,GAAG,EAAE,QAAQ,IAAI,IAAI,CAClE,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC,CAAiB,EAClB;YACE,OAAO,EAAE,IAAI;SACd,CACF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,QAAa,EACb,OAAgB;IAEhB,MAAM,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAmC,CAAC;IAC7E,IAAI,CAAC,OAAO,EAAE,MAAM;QAAE,OAAO;IAE7B,MAAM,QAAQ,GAAG,OAAO;QACtB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,KAAK,CAAC,KAAK,EAAE,MAAM;YACjB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC9D,CAAC,CAAC,IAAI,CACT;QACH,CAAC,CAAC,OAAO,CAAC;IAEZ,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,MAAM,GACT,QAAQ,CAAC,gBAAgB,CAAoC,IAAI,EAAE,CAAC;QACvE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,MAAM,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CACjC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,kBAAkB,CACzB,QAAa,EACb,IAAY,EACZ,OAAqB,EACrB,UAAiC,EAAE;IAEnC,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,iEAAiE,CACpE,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,EAAE,KAAc,EAAE,IAAe,EAAE,EAAE;QAC3D,IAAI,gBAAoC,CAAC;QACzC,IAAI,iBAAqC,CAAC;QAC1C,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,mBAAmB,GAAG,GAAG,EAAE;YAC/B,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,gBAAgB,CAAC;gBACxC,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,gBAAgB,GAAG,SAAS,CAAC;YAC/B,CAAC;YACD,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC;oBACF,KAAa,CAAC,IAAI,GAAG,iBAAiB,CAAC;gBAC1C,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,OAAQ,KAAa,CAAC,IAAI,CAAC;gBAC7B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAE,QAAQ,IAAI,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YACD,kEAAkE;YAClE,sEAAsE;YACtE,oEAAoE;YACpE,sCAAsC;YACtC,MAAM,QAAQ,GAAG,KAAY,CAAC;YAC9B,YAAY,GAAG,MAAM,IAAI,QAAQ,CAAC;YAClC,iBAAiB,GAAG,QAAQ,CAAC,IAAI,CAAC;YAClC,IAAI,CAAC;gBACH,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;gBACtC,uEAAuE;gBACvE,iEAAiE;gBACjE,kDAAkD;gBAClD,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;gBAC1C,QAAQ,CAAC,OAAO,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;gBACrD,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC;gBAChD,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC;gBACxC,QAAQ,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACnE,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;gBACnE,mEAAmE;YACrE,CAAC;QACH,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,oEAAoE;gBACpE,uEAAuE;gBACvE,mEAAmE;gBACnE,4DAA4D;gBAC5D,mBAAmB,EAAE,CAAC;gBACtB,OAAO,IAAI,EAAE,CAAC;YAChB,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,oEAAoE;YACpE,kEAAkE;YAClE,oEAAoE;YACpE,mEAAmE;YACnE,0BAA0B;YAC1B,MAAM,OAAO,GAAG,gBAAgB,IAAI,KAAK,CAAC,GAAG,EAAE,QAAQ,IAAI,EAAE,CAAC;YAC9D,MAAM,CAAC,GAAG,GAAU,CAAC;YACrB,MAAM,MAAM,GACV,OAAO,CAAC,EAAE,UAAU,KAAK,QAAQ;gBAC/B,CAAC,CAAC,CAAC,CAAC,UAAU;gBACd,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,QAAQ;oBAC7B,CAAC,CAAC,CAAC,CAAC,MAAM;oBACV,CAAC,CAAC,GAAG,CAAC;YACZ,OAAO,CAAC,KAAK,CACX,kBAAkB,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,OAAO,YAAY,MAAM,IAAI,EACrE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,OAAO,IAAI,CAAC,CAC5B,CAAC;YACF,uEAAuE;YACvE,sEAAsE;YACtE,mEAAmE;YACnE,gEAAgE;YAChE,mEAAmE;YACnE,6DAA6D;YAC7D,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAClB,kEAAkE;gBAClE,4DAA4D;gBAC5D,MAAM,CAAC,aAAa,CAAC;qBAClB,IAAI,CAAC,CAAC,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,EAAE,EAAE;oBACrD,IAAI,CAAC,qBAAqB,EAAE;wBAAE,OAAO;oBACrC,iBAAiB,CAAC,GAAG,EAAE;wBACrB,KAAK,EAAE,OAAO;wBACd,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,SAAS,EAAE,CAAC,GAAG,EAAE;4BACf,IAAI,CAAC;gCACH,OAAO,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC;4BACvD,CAAC;4BAAC,MAAM,CAAC;gCACP,OAAO,SAAS,CAAC;4BACnB,CAAC;wBACH,CAAC,CAAC,EAAE;qBACL,CAAC,CAAC;gBACL,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE;oBACV,gEAAgE;gBAClE,CAAC,CAAC,CAAC;YACP,CAAC;YACD,IAAI,CAAC;gBACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBACjC,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,kBAAkB,CAAC,CAAC;YAC/D,CAAC;YAAC,MAAM,CAAC;gBACP,uCAAuC;YACzC,CAAC;YACD,OAAO;gBACL,KAAK,EAAE,CAAC,EAAE,OAAO,IAAI,uBAAuB;gBAC5C,6DAA6D;gBAC7D,+DAA+D;gBAC/D,gEAAgE;gBAChE,0DAA0D;gBAC1D,+DAA+D;gBAC/D,oDAAoD;gBACpD,GAAG,CAAC,MAAM,IAAI,GAAG;oBACjB,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,GAAG;oBAC7C,CAAC,EAAE,KAAK;oBACN,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;oBACpB,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,kEAAkE;YAClE,YAAY;YACZ,mBAAmB,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,EAAE,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,uBAAuB,CAAC,QAAa;IAClD,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,MAAM,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,QAAQ,CAAC,yBAAyB,CAEtC,CAAC;QACd,MAAM,OAAO,GAAG,QAAQ;YACtB,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzD,CAAC,CAAC,iBAAiB,CAAC;QACtB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEjC,+DAA+D;QAC/D,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;QACtE,MAAM,kBAAkB,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACrE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACnD,MAAM,gBAAgB,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QAEjE,MAAM,cAAc,GAGhB;YACF,YAAY,EAAG,YAAoB,CAAC,sBAAsB;YAC1D,IAAI,EAAG,YAAoB,CAAC,iBAAiB;YAC7C,aAAa,EAAG,YAAoB,CAAC,uBAAuB;YAC5D,YAAY,EAAG,kBAA0B,CAAC,yBAAyB;YACnE,UAAU,EAAG,gBAAwB,CAAC,uBAAuB;YAC7D,GAAG,EAAG,SAAiB,CAAC,gBAAgB;YACxC,SAAS,EAAG,YAAoB,CAAC,sBAAsB;YACvD,MAAM,EAAG,YAAoB,CAAC,mBAAmB;YACjD,QAAQ,EAAG,cAAsB,CAAC,qBAAqB;SACxD,CAAC;QAEF,yEAAyE;QACzE,wEAAwE;QACxE,0EAA0E;QAC1E,qCAAqC;QACrC,IAAI,cAAc,GAGd,EAAE,CAAC;QACP,IAAI,CAAC;YACH,MAAM,EAAE,uBAAuB,EAAE,GAC/B,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;YAC9C,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,IAAI,CAAC;oBACH,MAAM,cAAc,GAAG,MAAM,uBAAuB,CAClD,EAAE,CAAC,WAAW,EACd,EAAE,CAAC,UAAU,CACd,CAAC;oBACF,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC5D,IAAI,CAAC,UAAU;4BAAE,SAAS;wBAC1B,MAAM,IAAI,GAAI,cAAsB,CAAC,UAAU,CAAC,CAAC;wBACjD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;4BAC/B,cAAc,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;wBAC9B,CAAC;oBACH,CAAC;oBACD,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;wBACtB,OAAO,CAAC,GAAG,CACT,iCAAiC,EAAE,CAAC,WAAW,2BAA2B,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnH,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,GAAG,GAAI,CAAW,CAAC,OAAO,IAAI,EAAE,CAAC;oBACvC,gEAAgE;oBAChE,6DAA6D;oBAC7D,gEAAgE;oBAChE,iEAAiE;oBACjE,wBAAwB;oBACxB,MAAM,UAAU,GAAG,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC;wBACvD,CAAC,CAAC,gEAAgE;4BAChE,qBAAqB;4BACrB,EAAE,CAAC,WAAW;4BACd,kEAAkE;wBACpE,CAAC,CAAC,EAAE,CAAC;oBACP,OAAO,CAAC,IAAI,CACV,gDAAgD,EAAE,CAAC,WAAW,YAAY,GAAG,GAAG,UAAU,EAAE,CAC7F,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,oEAAoE;QACtE,CAAC;QAED,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;YACnB,OAAO,CAAC,GAAG,CACT,gCAAgC,OAAO,CAAC,MAAM,uBAAuB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1F,CAAC;QAEJ,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,qEAAqE;YACrE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;YAC1D,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,CAAC,IAAI,CACV,sDAAsD,IAAI,GAAG,EAC5D,CAAW,CAAC,OAAO,CACrB,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,WAAmB,EACnB,UAAkB;IAElB,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,kBAAkB,CAAC,GAAG,WAAW,SAAS,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,QAAQ,GAAG,CAAC,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,sEAAsE;QACtE,wEAAwE;QACxE,mCAAmC;QACnC,MAAM,MAAM,GAAG,aAAa,CAC1B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CACtC,CAAC,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,WAAW,SAAS,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,OAAO,EAAE,CAAC;QACjB,wEAAwE;QACxE,8DAA8D;QAC9D,MAAM,QAAQ,IAAI,OAAO,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC","sourcesContent":["/**\n * Framework request handler — registers framework routes on Nitro's h3 instance.\n *\n * Nitro 3 exposes its h3 app as `nitroApp.h3`. We register framework routes\n * directly on it as middleware (`nitroApp.h3[\"~middleware\"]`), giving each\n * plugin a path-prefix-matched handler that runs before any file-based route.\n *\n * Plugins call `getH3App(nitroApp).use(path, handler)` exactly like h3 v1's\n * `app.use()` — the wrapper translates that into v2 middleware registration.\n *\n * Default plugins that the template doesn't provide are auto-mounted on the\n * first call to `getH3App()` per nitroApp instance.\n */\nimport type { EventHandler, H3Event } from \"h3\";\nimport { setResponseHeader, setResponseStatus } from \"h3\";\nimport { getMissingDefaultPlugins } from \"../deploy/route-discovery.js\";\n\nconst BOOTSTRAPPED = new WeakSet<object>();\nconst IN_BOOTSTRAP = new WeakSet<object>();\nconst FRAMEWORK_PREFIX = \"/_agent-native\";\nconst WELL_KNOWN_PREFIX = \"/.well-known\";\nconst APP_SHIM_KEY = \"_agentNativeH3Shim\";\nconst BOOTSTRAP_PROMISE_KEY = \"_agentNativeBootstrapPromise\";\nconst PLUGIN_READY_KEY = \"_agentNativePluginReadyPromise\";\nconst PLUGIN_READY_PLACEHOLDERS_KEY = \"_agentNativePluginReadyPlaceholders\";\nconst PROVIDED_PLUGIN_STEMS_KEY = \"_agentNativeProvidedPluginStems\";\n\ninterface PluginReadyEntry {\n promise: Promise<void>;\n paths?: string[];\n}\n\nfunction normalizeAppBasePath(value: string | undefined): string {\n if (!value || value === \"/\") return \"\";\n const trimmed = value.trim();\n if (!trimmed || trimmed === \"/\") return \"\";\n return `/${trimmed.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\")}`;\n}\n\nfunction getAppBasePath(): string {\n return normalizeAppBasePath(\n process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH,\n );\n}\n\nfunction pathMatchesPrefix(reqPath: string, prefix: string): boolean {\n return reqPath === prefix || reqPath.startsWith(prefix + \"/\");\n}\n\nfunction supportsAppBasePathMount(path: string): boolean {\n return (\n pathMatchesPrefix(path, FRAMEWORK_PREFIX) ||\n pathMatchesPrefix(path, WELL_KNOWN_PREFIX)\n );\n}\n\nfunction resolveMountMatch(\n reqPath: string,\n path: string,\n): { mountPath: string; strippedPath: string } | null {\n if (pathMatchesPrefix(reqPath, path)) {\n return { mountPath: path, strippedPath: reqPath.slice(path.length) || \"/\" };\n }\n\n const appBasePath = getAppBasePath();\n if (!appBasePath || !supportsAppBasePathMount(path)) return null;\n\n const prefixedPath = `${appBasePath}${path}`;\n if (!pathMatchesPrefix(reqPath, prefixedPath)) return null;\n return {\n mountPath: prefixedPath,\n strippedPath: reqPath.slice(prefixedPath.length) || \"/\",\n };\n}\n\n/**\n * Wrapper around Nitro's h3 instance that exposes a v1-style `.use()` API\n * for registering path-prefix middleware.\n */\nexport interface H3AppShim {\n use(path: string, handler: EventHandler): void;\n use(handler: EventHandler): void;\n}\n\n/**\n * Mark a default plugin slot as supplied by the app/template before the\n * framework default bootstrap runs.\n *\n * Bundled serverless functions often don't have the original\n * `server/plugins/*.ts` tree on disk at runtime, so filesystem route discovery\n * can falsely conclude a template plugin is missing. Explicit plugin factories\n * call this synchronously before awaiting bootstrap so the framework does not\n * auto-mount a generic default over the app's custom implementation.\n */\nexport function markDefaultPluginProvided(nitroApp: any, stem: string): void {\n if (!nitroApp || !stem) return;\n const existing = nitroApp[PROVIDED_PLUGIN_STEMS_KEY] as\n | Set<string>\n | undefined;\n const provided = existing ?? new Set<string>();\n provided.add(stem);\n nitroApp[PROVIDED_PLUGIN_STEMS_KEY] = provided;\n}\n\n/**\n * Get (or create) the shared H3 app wrapper for a nitroApp. Plugins use this\n * to register routes via `.use(path, handler)`.\n *\n * On the first call per nitroApp, we kick off auto-mounting any missing\n * default plugins. User-facing plugin factories (createAgentChatPlugin,\n * createAuthPlugin, etc.) await this bootstrap via `awaitBootstrap()` so the\n * default plugins finish registering middleware before requests arrive.\n */\nexport function getH3App(nitroApp: any): H3AppShim {\n if (!nitroApp) throw new Error(\"getH3App: nitroApp is required\");\n\n // Reuse the cached shim if we've wrapped this nitroApp before\n const cached = nitroApp[APP_SHIM_KEY] as H3AppShim | undefined;\n if (cached) return cached;\n\n const shim: H3AppShim = {\n use(arg1: string | EventHandler, arg2?: EventHandler) {\n const path = typeof arg1 === \"string\" ? arg1 : \"\";\n const handler = (typeof arg1 === \"string\" ? arg2 : arg1) as EventHandler;\n if (typeof handler !== \"function\") {\n throw new Error(\"getH3App.use: handler must be a function\");\n }\n registerMiddleware(nitroApp, path, handler);\n },\n };\n\n nitroApp[APP_SHIM_KEY] = shim;\n\n if (!BOOTSTRAPPED.has(nitroApp)) {\n BOOTSTRAPPED.add(nitroApp);\n nitroApp[BOOTSTRAP_PROMISE_KEY] = bootstrapDefaultPlugins(nitroApp).catch(\n (err) => {\n console.warn(\n \"[agent-native] Failed to auto-mount default plugins:\",\n (err as Error).message,\n );\n },\n );\n\n // Readiness gate: Nitro v3 doesn't await async plugins, so routes\n // registered inside an async plugin may not exist when the first\n // request arrives. These middleware entries hold framework routes\n // until default-plugin bootstrap and tracked plugin inits complete.\n const readinessGate = (async (event: H3Event) => {\n const eventAny = event as any;\n await awaitFrameworkRoutesReadyForRequest(\n nitroApp,\n eventAny.context?._mountedPathname ?? event.url?.pathname ?? \"\",\n );\n // Fall through — the actual route handler runs next.\n return undefined;\n }) as EventHandler;\n registerMiddleware(nitroApp, FRAMEWORK_PREFIX, readinessGate, {\n prepend: true,\n });\n registerMiddleware(nitroApp, WELL_KNOWN_PREFIX, readinessGate, {\n prepend: true,\n });\n }\n\n return shim;\n}\n\n/**\n * Wait for the framework's default-plugin bootstrap to complete.\n *\n * Called by user-facing plugin factories (`createAgentChatPlugin`, etc.) at\n * the top of their plugin function, so that by the time the function returns\n * — and Nitro starts accepting requests — all default plugins have finished\n * registering their middleware.\n *\n * No-op when called from inside the bootstrap itself (avoids deadlock when a\n * default plugin happens to be running as part of bootstrap).\n */\nexport async function awaitBootstrap(nitroApp: any): Promise<void> {\n if (!nitroApp || IN_BOOTSTRAP.has(nitroApp)) return;\n // Trigger bootstrap if it hasn't been already (idempotent — getH3App\n // creates the shim and kicks off bootstrap on first call).\n getH3App(nitroApp);\n const promise = nitroApp[BOOTSTRAP_PROMISE_KEY];\n if (promise) await promise;\n}\n\n/**\n * Wait until framework routes are safe to dispatch.\n *\n * Request-time gates must wait for both phases:\n * 1. default-plugin bootstrap, which discovers and starts missing plugins\n * 2. async plugin init promises, which register routes such as A2A cards\n */\nasync function awaitFrameworkRoutesReadyForRequest(\n nitroApp: any,\n reqPath: string,\n): Promise<void> {\n if (!nitroApp) return;\n const bootstrapPromise = nitroApp[BOOTSTRAP_PROMISE_KEY];\n if (bootstrapPromise) await bootstrapPromise;\n await awaitPluginsReady(nitroApp, reqPath);\n}\n\n/**\n * Track an async plugin's initialization promise. Nitro v3 calls plugins\n * synchronously and doesn't await async return values, so routes registered\n * inside an async plugin may not be ready when the first request arrives.\n *\n * Call this from the TOP of any async plugin so that the readiness gate\n * (installed by getH3App) can hold /_agent-native requests until the plugin\n * finishes mounting its routes.\n */\nexport function trackPluginInit(\n nitroApp: any,\n promise: Promise<void>,\n options: { paths?: string[] } = {},\n): void {\n if (!nitroApp) return;\n // Ensure the readiness gate exists even when the tracked plugin is the first\n // framework code to run in a serverless isolate. Otherwise an immediate\n // first request can fall through before the plugin registers its routes.\n getH3App(nitroApp);\n // Attach a no-op catch so the promise doesn't surface as an unhandled\n // rejection when Nitro v3 drops the async return value. The actual error\n // is still observable when awaitPluginsReady() re-awaits the promise.\n const safe = promise.catch((err) => {\n console.error(\n \"[agent-native] Plugin init failed:\",\n (err as Error).message || err,\n );\n });\n const entry: PluginReadyEntry = {\n promise: safe,\n paths: options.paths?.filter(Boolean),\n };\n const existing = nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined;\n if (existing) {\n existing.push(entry);\n } else {\n nitroApp[PLUGIN_READY_KEY] = [entry];\n }\n installPluginReadyPlaceholders(nitroApp, entry.paths);\n}\n\nfunction installPluginReadyPlaceholders(\n nitroApp: any,\n paths: string[] | undefined,\n): void {\n if (!paths?.length) return;\n const existing = nitroApp[PLUGIN_READY_PLACEHOLDERS_KEY] as\n | Set<string>\n | undefined;\n const installed = existing ?? new Set<string>();\n nitroApp[PLUGIN_READY_PLACEHOLDERS_KEY] = installed;\n\n const app = getH3App(nitroApp);\n for (const path of paths) {\n if (!path || installed.has(path)) continue;\n installed.add(path);\n registerMiddleware(\n nitroApp,\n path,\n (async (event: H3Event) => {\n const eventAny = event as any;\n await awaitFrameworkRoutesReadyForRequest(\n nitroApp,\n eventAny.context?._mountedPathname ?? event.url?.pathname ?? path,\n );\n return undefined;\n }) as EventHandler,\n {\n prepend: true,\n },\n );\n }\n}\n\n/**\n * Await all tracked plugin initializations. Called by the readiness gate\n * middleware before dispatching framework routes.\n */\nexport async function awaitPluginsReady(\n nitroApp: any,\n reqPath?: string,\n): Promise<void> {\n const entries = nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined;\n if (!entries?.length) return;\n\n const relevant = reqPath\n ? entries.filter((entry) =>\n entry.paths?.length\n ? entry.paths.some((path) => resolveMountMatch(reqPath, path))\n : true,\n )\n : entries;\n\n if (relevant.length) {\n await Promise.all(relevant.map((entry) => entry.promise));\n const completed = new Set(relevant);\n const latest =\n (nitroApp[PLUGIN_READY_KEY] as PluginReadyEntry[] | undefined) ?? [];\n nitroApp[PLUGIN_READY_KEY] = latest.filter(\n (entry) => !completed.has(entry),\n );\n }\n}\n\n/**\n * Register a path-prefix middleware on Nitro's h3 instance.\n *\n * The middleware:\n * - Returns `next()` (continues) if the request path doesn't match.\n * - Otherwise dispatches to the handler. If the handler returns a value,\n * it short-circuits the request. If it returns undefined, next() runs.\n *\n * Path matching emulates h3 v1's `app.use(path, ...)` behavior:\n * - Exact-match prefix: `/foo` matches `/foo`, `/foo/bar`, but not `/foobar`\n * - Empty path: middleware runs on every request\n */\nfunction registerMiddleware(\n nitroApp: any,\n path: string,\n handler: EventHandler,\n options: { prepend?: boolean } = {},\n) {\n const h3 = nitroApp.h3;\n if (!h3 || !Array.isArray(h3[\"~middleware\"])) {\n throw new Error(\n \"[agent-native] Cannot register route: nitroApp.h3 is not available. \" +\n \"Make sure you're calling getH3App() from inside a Nitro plugin.\",\n );\n }\n\n const middleware = async (event: H3Event, next: () => any) => {\n let originalPathname: string | undefined;\n let originalEventPath: string | undefined;\n let hadEventPath = false;\n const restoreOriginalPath = () => {\n if (originalPathname !== undefined) {\n try {\n event.url.pathname = originalPathname;\n } catch {\n // ignore\n }\n originalPathname = undefined;\n }\n if (hadEventPath) {\n try {\n (event as any).path = originalEventPath;\n } catch {\n // ignore\n }\n } else {\n try {\n delete (event as any).path;\n } catch {\n // ignore\n }\n }\n };\n if (path) {\n const reqPath = event.url?.pathname ?? \"\";\n const match = resolveMountMatch(reqPath, path);\n if (!match) {\n return next();\n }\n // Strip the mount prefix from event.url.pathname so handlers that\n // dispatch sub-routes can read `event.path` (or `event.url.pathname`)\n // and see the path RELATIVE to their mount point — matching h3 v1's\n // `app.use(path, handler)` semantics.\n const eventAny = event as any;\n hadEventPath = \"path\" in eventAny;\n originalEventPath = eventAny.path;\n try {\n originalPathname = event.url.pathname;\n // Save the full path in context so handlers that need the original URL\n // (e.g. Better Auth, which extracts its own basePath prefix) can\n // reconstruct a Request with the un-stripped URL.\n eventAny.context = eventAny.context ?? {};\n eventAny.context._mountedPathname = originalPathname;\n eventAny.context._mountPrefix = match.mountPath;\n event.url.pathname = match.strippedPath;\n eventAny.path = `${match.strippedPath}${event.url.search || \"\"}`;\n } catch {\n // event.url is read-only on some runtimes — fall through. Handlers\n // that don't depend on prefix stripping (most of them) still work.\n }\n }\n try {\n const result = await handler(event);\n if (result === undefined) {\n // Restore the original pathname BEFORE calling next() so downstream\n // middleware sees the full URL — not the stripped mount-relative path.\n // Matches h3 v2's own sub-app middleware pattern where the restore\n // happens inside the next() callback, not after it returns.\n restoreOriginalPath();\n return next();\n }\n return result;\n } catch (err) {\n // Log 500s to the server console so they're debuggable, and respond\n // with JSON instead of the default HTML error page so clients can\n // surface error messages. This only applies to routes mounted under\n // the framework prefix (or middleware mounted at `/`, for which we\n // still want visibility).\n const reqPath = originalPathname ?? event.url?.pathname ?? \"\";\n const e = err as any;\n const status =\n typeof e?.statusCode === \"number\"\n ? e.statusCode\n : typeof e?.status === \"number\"\n ? e.status\n : 500;\n console.error(\n `[agent-native] ${event.method ?? \"\"} ${reqPath} failed (${status}):`,\n e?.stack || e?.message || e,\n );\n // Forward 5xx to server-side Sentry — Nitro's own `error` hook may not\n // fire here because we convert the throw into a normal JSON response,\n // and a console.error alone is invisible in deployed environments.\n // 4xx are user-input errors (validation, auth) and aren't worth\n // alerting on. Lazy-loaded so the framework-request-handler module\n // doesn't pull @sentry/node into bundles that don't need it.\n if (status >= 500) {\n // Static `import` would create a cycle (sentry.ts imports auth.ts\n // which imports… eventually, framework-request-handler.ts).\n import(\"./sentry.js\")\n .then(({ captureRouteError, isServerSentryEnabled }) => {\n if (!isServerSentryEnabled()) return;\n captureRouteError(err, {\n route: reqPath,\n method: event.method,\n userAgent: (() => {\n try {\n return event.headers?.get(\"user-agent\") ?? undefined;\n } catch {\n return undefined;\n }\n })(),\n });\n })\n .catch(() => {\n // Sentry is observability — never let it break a response path.\n });\n }\n try {\n setResponseStatus(event, status);\n setResponseHeader(event, \"content-type\", \"application/json\");\n } catch {\n // Response already sent — best effort.\n }\n return {\n error: e?.message || \"Internal server error\",\n // Only surface the stack to clients when explicitly enabled.\n // `NODE_ENV !== \"production\"` was unsafe — preview deploys and\n // any host that forgets to set NODE_ENV=production leaked stack\n // traces (file paths, dependency versions, internal route\n // topology) to anonymous callers. Operators who want stacks in\n // dev set `AGENT_NATIVE_DEBUG_ERRORS=1` explicitly.\n ...(status >= 500 &&\n process.env.AGENT_NATIVE_DEBUG_ERRORS === \"1\" &&\n e?.stack\n ? { stack: e.stack }\n : {}),\n };\n } finally {\n // Restore the original pathname so downstream middleware sees the\n // full URL.\n restoreOriginalPath();\n }\n };\n\n if (options.prepend) {\n h3[\"~middleware\"].unshift(middleware);\n } else {\n h3[\"~middleware\"].push(middleware);\n }\n}\n\n/**\n * Auto-mount any default framework plugins that the template doesn't provide.\n *\n * Runs once per nitroApp on the first `getH3App()` call. Uses route-discovery\n * to find which default plugin stems are missing from `server/plugins/`, then\n * dynamically imports and mounts them. If a workspace core is present in the\n * ancestor chain, plugin slots the workspace core exports are mounted from\n * there instead of from @agent-native/core — this is the middle layer of the\n * three-layer inheritance model (app local > workspace core > framework).\n */\nasync function bootstrapDefaultPlugins(nitroApp: any): Promise<void> {\n IN_BOOTSTRAP.add(nitroApp);\n try {\n const cwd = process.cwd();\n const discoveredMissing = await getMissingDefaultPlugins(cwd);\n const provided = nitroApp[PROVIDED_PLUGIN_STEMS_KEY] as\n | Set<string>\n | undefined;\n const missing = provided\n ? discoveredMissing.filter((stem) => !provided.has(stem))\n : discoveredMissing;\n if (missing.length === 0) return;\n\n // Lazy import to avoid circular dependency at module load time\n const serverModule = await import(\"./index.js\");\n const terminalModule = await import(\"../terminal/terminal-plugin.js\");\n const integrationsModule = await import(\"../integrations/plugin.js\");\n const orgModule = await import(\"../org/plugin.js\");\n const onboardingModule = await import(\"../onboarding/plugin.js\");\n\n const frameworkImpls: Record<\n string,\n ((nitroApp: any) => void | Promise<void>) | undefined\n > = {\n \"agent-chat\": (serverModule as any).defaultAgentChatPlugin,\n auth: (serverModule as any).defaultAuthPlugin,\n \"core-routes\": (serverModule as any).defaultCoreRoutesPlugin,\n integrations: (integrationsModule as any).defaultIntegrationsPlugin,\n onboarding: (onboardingModule as any).defaultOnboardingPlugin,\n org: (orgModule as any).defaultOrgPlugin,\n resources: (serverModule as any).defaultResourcesPlugin,\n sentry: (serverModule as any).defaultSentryPlugin,\n terminal: (terminalModule as any).defaultTerminalPlugin,\n };\n\n // Workspace core layer: if the app is inside an enterprise monorepo with\n // `agent-native.workspaceCore` configured, pull in any plugin slots the\n // workspace core exports from its server entry. We dynamically import the\n // workspace core package at runtime.\n let workspaceImpls: Record<\n string,\n ((nitroApp: any) => void | Promise<void>) | undefined\n > = {};\n try {\n const { getWorkspaceCoreExports } =\n await import(\"../deploy/workspace-core.js\");\n const ws = await getWorkspaceCoreExports(cwd);\n if (ws && Object.keys(ws.plugins).length > 0) {\n try {\n const wsServerModule = await loadWorkspaceCoreServer(\n ws.packageName,\n ws.packageDir,\n );\n for (const [slot, exportName] of Object.entries(ws.plugins)) {\n if (!exportName) continue;\n const impl = (wsServerModule as any)[exportName];\n if (typeof impl === \"function\") {\n workspaceImpls[slot] = impl;\n }\n }\n if (process.env.DEBUG) {\n console.log(\n `[agent-native] Workspace core ${ws.packageName} provides plugin slots: ${Object.keys(workspaceImpls).join(\", \")}`,\n );\n }\n } catch (e) {\n const msg = (e as Error).message ?? \"\";\n // Common cause: workspace-core's package.json points \"./server\"\n // at a TS source file (the scaffold default), but Node can't\n // resolve relative `.js` imports inside it without a TS loader.\n // Tell the user to compile to dist/ rather than just dumping the\n // raw resolution error.\n const tsLoadHint = /\\.js' imported from .*\\.ts/.test(msg)\n ? \" — workspace-core src is TypeScript but isn't being compiled. \" +\n \"Run `pnpm --filter \" +\n ws.packageName +\n \" build` and point its `./server` export at dist/server/index.js.\"\n : \"\";\n console.warn(\n `[agent-native] Failed to load workspace core ${ws.packageName}/server: ${msg}${tsLoadHint}`,\n );\n }\n }\n } catch {\n // Workspace shared package isn't available (e.g. running on an edge\n // runtime without fs). Silently fall through to framework defaults.\n }\n\n if (process.env.DEBUG)\n console.log(\n `[agent-native] Auto-mounting ${missing.length} default plugin(s): ${missing.join(\", \")}`,\n );\n\n for (const stem of missing) {\n // Prefer workspace-core impl over framework default when both exist.\n const impl = workspaceImpls[stem] ?? frameworkImpls[stem];\n if (typeof impl === \"function\") {\n try {\n await impl(nitroApp);\n } catch (e) {\n console.warn(\n `[agent-native] Failed to auto-mount default plugin ${stem}:`,\n (e as Error).message,\n );\n }\n }\n }\n } finally {\n IN_BOOTSTRAP.delete(nitroApp);\n }\n}\n\n/**\n * Load a workspace-core's `/server` entry, transparently handling TS source.\n *\n * The scaffolded workspace-core template ships TS sources without a build\n * step (exports point at `./src/server/index.ts`), so plain `await import()`\n * blows up the moment Node hits a relative `.js` import inside (the standard\n * TS ESM convention) — and even before that, Node may resolve the package\n * relative to the framework's own location rather than the user's monorepo.\n *\n * We try Node's plain `import()` first (fastest path when the user has\n * compiled to dist/) and fall through to jiti on any error. jiti is anchored\n * to a real file inside the workspace-core's directory, so its module\n * resolution starts in the right node_modules tree (handles pnpm hoisting\n * and linked workspaces) AND handles TS source files + `.js` → `.ts` ESM\n * extension remapping.\n *\n * Edge runtimes without `fs` won't be able to load jiti at all; the outer\n * try/catch silently falls through to framework defaults in that case.\n */\nexport async function loadWorkspaceCoreServer(\n packageName: string,\n packageDir: string,\n): Promise<any> {\n let firstErr: unknown;\n try {\n return await import(/* @vite-ignore */ `${packageName}/server`);\n } catch (e) {\n firstErr = e;\n }\n\n try {\n const { createJiti } = await import(\"jiti\");\n const { pathToFileURL } = await import(\"node:url\");\n const path = await import(\"node:path\");\n // Anchor jiti to a real file inside the workspace-core package so its\n // module resolution starts in the right node_modules tree (handles pnpm\n // hoisting and linked workspaces).\n const anchor = pathToFileURL(\n path.join(packageDir, \"package.json\"),\n ).toString();\n const jiti = createJiti(anchor, { interopDefault: true });\n return await jiti.import(`${packageName}/server`);\n } catch (jitiErr) {\n // jiti also failed — rethrow the original Node error since it's usually\n // more informative about *why* the package wasn't resolvable.\n throw firstErr ?? jitiErr;\n }\n}\n\nexport { FRAMEWORK_PREFIX };\n"]}
|
package/docs/content/dispatch.md
CHANGED
|
@@ -47,9 +47,19 @@ The behavioral rule lives in the dispatch agent's instructions: domain work belo
|
|
|
47
47
|
|
|
48
48
|
### Unified MCP gateway
|
|
49
49
|
|
|
50
|
-
Dispatch can also be the single MCP
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
Dispatch can also be the single MCP connector for external agents. Add
|
|
51
|
+
`https://dispatch.agent-native.com/_agent-native/mcp` once in Claude, ChatGPT,
|
|
52
|
+
Codex, Cursor, or another MCP host, sign in through the host's OAuth flow, then
|
|
53
|
+
manage which apps that gateway can reach from Dispatch's **Agents** page. The
|
|
54
|
+
gateway exposes `list_apps`, `ask_app`, and `open_app`, filtered by the
|
|
55
|
+
selected app grants, so external agents can route work to Mail, Calendar,
|
|
56
|
+
Analytics, Brain, and workspace apps without a separate authorization for every
|
|
57
|
+
app.
|
|
58
|
+
|
|
59
|
+
Direct per-app MCP URLs such as
|
|
60
|
+
`https://mail.agent-native.com/_agent-native/mcp` still exist when you
|
|
61
|
+
intentionally want one isolated app surface. For most workspace use, the
|
|
62
|
+
Dispatch gateway is the lower-friction path.
|
|
53
63
|
|
|
54
64
|
### Workspace resources
|
|
55
65
|
|
|
@@ -12,28 +12,45 @@ The external-agent bridge closes the loop. First you connect your own agent to a
|
|
|
12
12
|
|
|
13
13
|
## Easy setup {#easy-setup}
|
|
14
14
|
|
|
15
|
-
Add
|
|
15
|
+
Add one remote MCP connector to the host where you want to use Agent-Native.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
For workspace or cross-app work, use Dispatch:
|
|
18
18
|
|
|
19
19
|
```text
|
|
20
20
|
https://dispatch.agent-native.com/_agent-native/mcp
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Dispatch
|
|
23
|
+
Dispatch is the single gateway for Mail, Calendar, Analytics, Brain, and your
|
|
24
|
+
workspace apps. In Dispatch's **Agents** page, choose whether the gateway can
|
|
25
|
+
reach all apps or only selected apps. The connected host then gets
|
|
26
|
+
`list_apps`, `ask_app`, and `open_app`, filtered to that granted set.
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
For one intentionally isolated app, use that app directly:
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
```text
|
|
31
|
+
https://mail.agent-native.com/_agent-native/mcp
|
|
32
|
+
https://<your-app>.agent-native.com/_agent-native/mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Every hosted app also has a helper page at
|
|
36
|
+
`https://<app>/_agent-native/mcp/connect` with the copyable URL and
|
|
37
|
+
host-specific tabs for Claude, ChatGPT, Cursor, Claude Code, Codex, and Other.
|
|
38
|
+
|
|
39
|
+
### Claude and ChatGPT OAuth {#oauth}
|
|
40
|
+
|
|
41
|
+
Claude / Claude Desktop: add a custom connector, paste the MCP URL, click
|
|
42
|
+
**Connect**, sign in with your Agent-Native account, approve the MCP scopes,
|
|
43
|
+
and enable the connector in a chat. Claude Code uses the same URL: add it as a
|
|
44
|
+
remote HTTP MCP server, run `/mcp`, then choose **Authenticate**.
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
| Analytics | `https://analytics.agent-native.com/_agent-native/mcp` |
|
|
34
|
-
| Any app | `https://<app-host>/_agent-native/mcp` |
|
|
46
|
+
ChatGPT: use a workspace where custom MCP connectors or developer-mode apps are
|
|
47
|
+
enabled, create a custom connector/app, paste the same MCP URL, choose OAuth,
|
|
48
|
+
scan/discover tools, sign in with Agent-Native, approve the scopes, and enable
|
|
49
|
+
the connector in a chat.
|
|
35
50
|
|
|
36
|
-
|
|
51
|
+
OAuth grants are per host and per user. The host stores the tokens and
|
|
52
|
+
mediates tool/resource calls, so inline MCP App previews never receive raw
|
|
53
|
+
OAuth tokens. The scopes are:
|
|
37
54
|
|
|
38
55
|
| Scope | What it enables |
|
|
39
56
|
| ----------- | ---------------------------------------------------- |
|
|
@@ -41,54 +58,9 @@ When the chat host asks you to authorize Agent-Native, sign in with your workspa
|
|
|
41
58
|
| `mcp:write` | Drafting, updating, and other mutating actions |
|
|
42
59
|
| `mcp:apps` | Inline MCP Apps, charts, dashboards, drafts, and UIs |
|
|
43
60
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
1. Open Claude.
|
|
49
|
-
2. Go to **Customize → Connectors**.
|
|
50
|
-
3. Choose **Add custom connector**.
|
|
51
|
-
4. Paste the remote MCP URL for the app.
|
|
52
|
-
5. Click **Connect**.
|
|
53
|
-
6. Sign in with your Agent-Native account, then approve `mcp:read`, `mcp:write`, and `mcp:apps`.
|
|
54
|
-
7. Start a chat and enable the connector from the connector/tools menu.
|
|
55
|
-
|
|
56
|
-
For Team or Enterprise workspaces, an owner or admin may need to add the connector under organization settings first. Each user still connects their own account once, so tool calls run as the signed-in user.
|
|
57
|
-
|
|
58
|
-
### ChatGPT web {#chatgpt}
|
|
59
|
-
|
|
60
|
-
ChatGPT's full MCP connector flow is currently workspace/admin gated. Use ChatGPT web in a workspace where custom MCP connectors are enabled.
|
|
61
|
-
|
|
62
|
-
1. In ChatGPT, open **Workspace settings**.
|
|
63
|
-
2. Enable the setting that allows custom MCP connectors or developer-mode connectors.
|
|
64
|
-
3. Go to **Apps** or **Connectors**, then choose **Create** or **Add custom connector**.
|
|
65
|
-
4. Paste the remote MCP URL for the app.
|
|
66
|
-
5. Choose OAuth authentication.
|
|
67
|
-
6. Scan or discover tools.
|
|
68
|
-
7. Sign in with your Agent-Native account and approve the MCP scopes.
|
|
69
|
-
8. Create the connector, then select it from a new chat's tools/apps menu.
|
|
70
|
-
|
|
71
|
-
If the ChatGPT workspace does not expose custom MCP connectors, ask a workspace admin to enable them first.
|
|
72
|
-
|
|
73
|
-
#### Recovering "Connector name already exists" {#chatgpt-drafts}
|
|
74
|
-
|
|
75
|
-
ChatGPT creates a **draft** the moment you click **Create app** — even if you closed the OAuth popup before approving the scopes. The draft is not visible under **Enabled apps**, but it still owns the name, so retrying with the same name surfaces a `"Connector name already exists"` toast. Recovery is fully self-service in the ChatGPT UI:
|
|
76
|
-
|
|
77
|
-
1. Open **Settings → Apps**.
|
|
78
|
-
2. Scroll past **Enabled apps** and **Advanced settings** to the **Drafts** section (labeled _"Private apps you've created in developer mode"_).
|
|
79
|
-
3. Click the draft with the conflicting name.
|
|
80
|
-
4. Either press **Connect** to finish OAuth in place (no rename needed), or open the **⋯** overflow menu and choose **Delete** and re-add via **Advanced settings → Create app**.
|
|
81
|
-
|
|
82
|
-
There is no "Drafts" tab on the **Add more / app directory** dialog, so non-admins sometimes miss the section entirely — it lives further down the same Settings → Apps page that lists enabled apps.
|
|
83
|
-
|
|
84
|
-
### Cursor {#cursor}
|
|
85
|
-
|
|
86
|
-
1. Open Cursor → **Settings → MCP**.
|
|
87
|
-
2. Click **Add MCP Server**.
|
|
88
|
-
3. Paste the remote MCP URL for the app and save.
|
|
89
|
-
4. When Cursor prompts, sign in with your Agent-Native account and approve `mcp:read`, `mcp:write`, and `mcp:apps`.
|
|
90
|
-
|
|
91
|
-
Cursor supports remote-OAuth MCP servers, so the paste-URL flow works the same as Claude — no terminal involved. Goose, Postman, MCPJam, and VS Code GitHub Copilot accept the same URL through their own MCP-server UIs once OAuth support is enabled in your build.
|
|
61
|
+
Cursor, Goose, Postman, MCPJam, and VS Code GitHub Copilot use the same remote
|
|
62
|
+
MCP URL through their own MCP-server UIs when their build supports remote OAuth
|
|
63
|
+
MCP servers.
|
|
92
64
|
|
|
93
65
|
### Quick test prompt {#quick-test}
|
|
94
66
|
|
|
@@ -136,13 +108,15 @@ Restart the agent client after connecting so it picks up the new MCP server; OAu
|
|
|
136
108
|
|
|
137
109
|
Use `--client codex` (or `--client claude-code`, `--client claude-code-cli`, `--client cowork`, `--client all`) to skip the picker for scripts or one-off installs.
|
|
138
110
|
|
|
139
|
-
When you truly need isolated
|
|
111
|
+
When you truly need an isolated app instead of Dispatch's workspace gateway,
|
|
112
|
+
run the same command with that app's host:
|
|
140
113
|
|
|
141
114
|
```bash
|
|
142
|
-
npx @agent-native/core connect
|
|
115
|
+
npx @agent-native/core connect https://mail.agent-native.com
|
|
143
116
|
```
|
|
144
117
|
|
|
145
|
-
|
|
118
|
+
`connect --all` still exists for legacy per-app client setups, but new
|
|
119
|
+
workspace setups should prefer the single Dispatch connector.
|
|
146
120
|
|
|
147
121
|
The connection is **per-user, scoped, and revocable**. In the OAuth path, the host stores the tokens after `/mcp` authentication; in the fallback path, the browser session you authorized with is the identity the agent acts as. Nothing exposes the deployment's shared secret.
|
|
148
122
|
|
|
@@ -172,14 +146,14 @@ Use this manual bearer block for MCP clients that cannot complete the standard r
|
|
|
172
146
|
Hosted agent-native apps also support the standard remote MCP OAuth flow. For clients that implement MCP OAuth, add the remote HTTP server URL with no static headers:
|
|
173
147
|
|
|
174
148
|
```bash
|
|
175
|
-
claude mcp add --transport http agent-native
|
|
176
|
-
https://
|
|
149
|
+
claude mcp add --transport http agent-native \
|
|
150
|
+
https://dispatch.agent-native.com/_agent-native/mcp
|
|
177
151
|
```
|
|
178
152
|
|
|
179
153
|
This is the same URL-only entry that `agent-native connect https://dispatch.agent-native.com --client claude-code` writes for you. Then run `/mcp` in Claude Code and choose **Authenticate**. The client discovers auth from the MCP server's `401 WWW-Authenticate` challenge, fetches `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`, dynamically registers a public OAuth client, opens the app's authorization page, and stores the resulting token securely. ChatGPT developer-mode connectors use the same server URL:
|
|
180
154
|
|
|
181
155
|
```text
|
|
182
|
-
https://
|
|
156
|
+
https://dispatch.agent-native.com/_agent-native/mcp
|
|
183
157
|
```
|
|
184
158
|
|
|
185
159
|
The OAuth flow is authorization-code + PKCE with refresh-token rotation. Access tokens are audience-bound to the exact MCP resource URL and carry the signed user/org identity, so tool calls, `resources/read`, and MCP App iframe-initiated `tools/call` all run through the same `runWithRequestContext` tenant scoping as the existing connect-minted JWT path. The iframe never receives raw OAuth tokens; the host mediates calls through the authenticated MCP connection.
|
|
@@ -538,7 +512,7 @@ The fallback hosted `connect` flow never copies the deployment's shared secret.
|
|
|
538
512
|
|
|
539
513
|
**Do**
|
|
540
514
|
|
|
541
|
-
- Connect your own agent to
|
|
515
|
+
- Connect your own agent to Dispatch with `npx @agent-native/core connect https://dispatch.agent-native.com`; use a direct app URL only when you want one isolated app.
|
|
542
516
|
- Add a `link` builder to any action that produces or lists a navigable resource (draft, event, dashboard, document).
|
|
543
517
|
- Build the URL with `buildDeepLink(...)` — the single source of truth for the open-route format.
|
|
544
518
|
- Keep `link` pure and synchronous; return `null` when there's nothing to open.
|
|
@@ -7,7 +7,7 @@ description: "Expose your agent-native app as a remote MCP server so Claude, Cha
|
|
|
7
7
|
|
|
8
8
|
Every agent-native app automatically exposes a remote MCP (Model Context Protocol) server. This lets external AI tools like Claude, ChatGPT custom MCP apps, Claude Code, Cursor, Codex, VS Code GitHub Copilot, and Windsurf discover and call your app's actions directly — no extra code needed.
|
|
9
9
|
|
|
10
|
-
If your goal is to connect Claude, ChatGPT, Claude Code, Codex, Cursor, or Claude Cowork to
|
|
10
|
+
If your goal is to connect Claude, ChatGPT, Claude Code, Codex, Cursor, or Claude Cowork to hosted agent-native apps, start with [External Agents](/docs/external-agents). It documents the recommended single Dispatch connector at `https://dispatch.agent-native.com/_agent-native/mcp`, direct per-app URLs for isolated app access, standard remote MCP OAuth, fallback config for older clients, MCP Apps inline UIs, and deep links back into the UI. This page is the lower-level MCP server reference.
|
|
11
11
|
|
|
12
12
|
## Overview {#overview}
|
|
13
13
|
|
|
@@ -188,14 +188,14 @@ The MCP endpoint supports standard remote MCP OAuth plus the existing bearer-tok
|
|
|
188
188
|
For OAuth-capable MCP hosts, configure the remote server URL with no static headers:
|
|
189
189
|
|
|
190
190
|
```bash
|
|
191
|
-
claude mcp add --transport http agent-native
|
|
191
|
+
claude mcp add --transport http agent-native https://dispatch.agent-native.com/_agent-native/mcp
|
|
192
192
|
```
|
|
193
193
|
|
|
194
194
|
The first unauthenticated MCP request receives:
|
|
195
195
|
|
|
196
196
|
```http
|
|
197
197
|
HTTP/1.1 401 Unauthorized
|
|
198
|
-
WWW-Authenticate: Bearer resource_metadata="https://
|
|
198
|
+
WWW-Authenticate: Bearer resource_metadata="https://dispatch.agent-native.com/.well-known/oauth-protected-resource", scope="mcp:read mcp:write mcp:apps"
|
|
199
199
|
```
|
|
200
200
|
|
|
201
201
|
Discovery endpoints:
|
|
@@ -56,6 +56,11 @@ Day-to-day, Dispatch is the place admins and ops folks open to keep the workspac
|
|
|
56
56
|
and credential references, then grant apps such as Brain, Analytics, Mail, or
|
|
57
57
|
Dispatch access without copying raw secrets. App-specific source
|
|
58
58
|
configuration stays in the app that uses the provider.
|
|
59
|
+
- **Expose one MCP connector.** Add
|
|
60
|
+
`https://dispatch.agent-native.com/_agent-native/mcp` in Claude, ChatGPT,
|
|
61
|
+
Codex, Cursor, or another MCP host, then choose which workspace apps the
|
|
62
|
+
connector can reach from Dispatch's **Agents** page. Use a direct app URL
|
|
63
|
+
only when that host should be isolated to one app.
|
|
59
64
|
- **Keep company context global.** Put personas, positioning, messaging, company facts, brand guidelines, and guardrails in Dispatch Resources once, then preview the effective workspace -> app/org -> personal stack for any app/user or inspect the stack from an app card's Context view.
|
|
60
65
|
- **Set up recurring jobs.** "Every Monday at 7am, ask the analytics agent for last week's signups and email me a summary." See [Recurring Jobs](/docs/recurring-jobs).
|
|
61
66
|
- **Review dream proposals.** Dispatch Dreams inspect prior agent runs and create source-backed proposals for what the workspace should remember, which stale notes should be cleaned up, and which repeated lessons should become skills or jobs.
|
|
@@ -71,7 +76,7 @@ _How it works under the hood (for developers)._
|
|
|
71
76
|
- **Remote agent registry.** A2A manifests live in `remote-agents/*.json` — one per app. Dispatch calls them using the `call-agent` action. In a multi-app workspace, sibling apps under `apps/` are auto-discovered as A2A peers — no manual registration needed.
|
|
72
77
|
- **Vault schema.** Drizzle tables for secrets, grants, requests, approvals, and audit logs. See `server/db/schema.ts` in the template.
|
|
73
78
|
- **Slack / Telegram plugins.** Server plugins that register webhooks and forward incoming messages to the orchestrator agent.
|
|
74
|
-
- **MCP hub mode.** Dispatch can act as the workspace's [MCP hub](/docs/mcp-clients#hub) so every other app in the workspace pulls the same org-scope MCP server list.
|
|
79
|
+
- **MCP hub mode.** Dispatch can act as the workspace's [MCP hub](/docs/mcp-clients#hub) so every other app in the workspace pulls the same org-scope MCP server list. Separately, Dispatch's own `/_agent-native/mcp` endpoint is the recommended external MCP connector for Claude, ChatGPT, and other hosts that should reach multiple workspace apps.
|
|
75
80
|
|
|
76
81
|
## Dreams {#dreams}
|
|
77
82
|
|
package/package.json
CHANGED