@agent-native/core 0.22.5 → 0.22.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  2. package/dist/agent/engine/builder-engine.js +4 -2
  3. package/dist/agent/engine/builder-engine.js.map +1 -1
  4. package/dist/agent/engine/builder-gateway-headers.d.ts +10 -0
  5. package/dist/agent/engine/builder-gateway-headers.d.ts.map +1 -0
  6. package/dist/agent/engine/builder-gateway-headers.js +44 -0
  7. package/dist/agent/engine/builder-gateway-headers.js.map +1 -0
  8. package/dist/agent/engine/index.d.ts +1 -1
  9. package/dist/agent/engine/index.d.ts.map +1 -1
  10. package/dist/agent/engine/index.js +1 -1
  11. package/dist/agent/engine/index.js.map +1 -1
  12. package/dist/agent/engine/registry.d.ts +1 -0
  13. package/dist/agent/engine/registry.d.ts.map +1 -1
  14. package/dist/agent/engine/registry.js +51 -0
  15. package/dist/agent/engine/registry.js.map +1 -1
  16. package/dist/agent/engine/translate-ai-sdk.d.ts.map +1 -1
  17. package/dist/agent/engine/translate-ai-sdk.js +3 -2
  18. package/dist/agent/engine/translate-ai-sdk.js.map +1 -1
  19. package/dist/agent/engine/translate-anthropic.d.ts +36 -2
  20. package/dist/agent/engine/translate-anthropic.d.ts.map +1 -1
  21. package/dist/agent/engine/translate-anthropic.js +159 -6
  22. package/dist/agent/engine/translate-anthropic.js.map +1 -1
  23. package/dist/agent/engine/types.d.ts +4 -2
  24. package/dist/agent/engine/types.d.ts.map +1 -1
  25. package/dist/agent/engine/types.js.map +1 -1
  26. package/dist/agent/production-agent.d.ts.map +1 -1
  27. package/dist/agent/production-agent.js +69 -9
  28. package/dist/agent/production-agent.js.map +1 -1
  29. package/dist/agent/types.d.ts +2 -0
  30. package/dist/agent/types.d.ts.map +1 -1
  31. package/dist/agent/types.js.map +1 -1
  32. package/dist/cli/connect.d.ts +1 -1
  33. package/dist/cli/connect.d.ts.map +1 -1
  34. package/dist/cli/connect.js +5 -2
  35. package/dist/cli/connect.js.map +1 -1
  36. package/dist/cli/create.d.ts.map +1 -1
  37. package/dist/cli/create.js +48 -6
  38. package/dist/cli/create.js.map +1 -1
  39. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  40. package/dist/client/MultiTabAssistantChat.js +4 -3
  41. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  42. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  43. package/dist/client/NewWorkspaceAppFlow.js +1 -0
  44. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  45. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  46. package/dist/client/agent-chat-adapter.js +11 -5
  47. package/dist/client/agent-chat-adapter.js.map +1 -1
  48. package/dist/client/api-path.d.ts.map +1 -1
  49. package/dist/client/api-path.js +2 -0
  50. package/dist/client/api-path.js.map +1 -1
  51. package/dist/client/embed-auth.d.ts +4 -0
  52. package/dist/client/embed-auth.d.ts.map +1 -0
  53. package/dist/client/embed-auth.js +102 -0
  54. package/dist/client/embed-auth.js.map +1 -0
  55. package/dist/client/index.d.ts +1 -0
  56. package/dist/client/index.d.ts.map +1 -1
  57. package/dist/client/index.js +1 -0
  58. package/dist/client/index.js.map +1 -1
  59. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  60. package/dist/client/settings/SettingsPanel.js +7 -3
  61. package/dist/client/settings/SettingsPanel.js.map +1 -1
  62. package/dist/client/use-action.d.ts.map +1 -1
  63. package/dist/client/use-action.js +2 -0
  64. package/dist/client/use-action.js.map +1 -1
  65. package/dist/client/use-chat-models.d.ts.map +1 -1
  66. package/dist/client/use-chat-models.js +4 -3
  67. package/dist/client/use-chat-models.js.map +1 -1
  68. package/dist/client/use-db-sync.d.ts.map +1 -1
  69. package/dist/client/use-db-sync.js +4 -0
  70. package/dist/client/use-db-sync.js.map +1 -1
  71. package/dist/deploy/route-discovery.js +1 -1
  72. package/dist/deploy/route-discovery.js.map +1 -1
  73. package/dist/index.d.ts +2 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +2 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/mcp/build-server.d.ts.map +1 -1
  78. package/dist/mcp/build-server.js +49 -21
  79. package/dist/mcp/build-server.js.map +1 -1
  80. package/dist/mcp/builtin-tools.d.ts +1 -0
  81. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  82. package/dist/mcp/builtin-tools.js +147 -8
  83. package/dist/mcp/builtin-tools.js.map +1 -1
  84. package/dist/mcp/connect-route.d.ts.map +1 -1
  85. package/dist/mcp/connect-route.js +79 -51
  86. package/dist/mcp/connect-route.js.map +1 -1
  87. package/dist/mcp/embed-app.d.ts +14 -0
  88. package/dist/mcp/embed-app.d.ts.map +1 -0
  89. package/dist/mcp/embed-app.js +191 -0
  90. package/dist/mcp/embed-app.js.map +1 -0
  91. package/dist/mcp/index.d.ts +1 -0
  92. package/dist/mcp/index.d.ts.map +1 -1
  93. package/dist/mcp/index.js +1 -0
  94. package/dist/mcp/index.js.map +1 -1
  95. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  96. package/dist/scripts/agent-engines/list-agent-engines.js +2 -1
  97. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  98. package/dist/scripts/agent-engines/manage-agent-engine.d.ts.map +1 -1
  99. package/dist/scripts/agent-engines/manage-agent-engine.js +4 -1
  100. package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
  101. package/dist/scripts/agent-engines/set-agent-engine.d.ts.map +1 -1
  102. package/dist/scripts/agent-engines/set-agent-engine.js +4 -1
  103. package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
  104. package/dist/server/action-discovery.d.ts.map +1 -1
  105. package/dist/server/action-discovery.js +10 -1
  106. package/dist/server/action-discovery.js.map +1 -1
  107. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  108. package/dist/server/agent-chat-plugin.js +9 -1
  109. package/dist/server/agent-chat-plugin.js.map +1 -1
  110. package/dist/server/auth.d.ts +7 -6
  111. package/dist/server/auth.d.ts.map +1 -1
  112. package/dist/server/auth.js +28 -13
  113. package/dist/server/auth.js.map +1 -1
  114. package/dist/server/core-routes-plugin.d.ts +2 -0
  115. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  116. package/dist/server/core-routes-plugin.js +7 -0
  117. package/dist/server/core-routes-plugin.js.map +1 -1
  118. package/dist/server/embed-route.d.ts +8 -0
  119. package/dist/server/embed-route.d.ts.map +1 -0
  120. package/dist/server/embed-route.js +71 -0
  121. package/dist/server/embed-route.js.map +1 -0
  122. package/dist/server/embed-session.d.ts +65 -0
  123. package/dist/server/embed-session.d.ts.map +1 -0
  124. package/dist/server/embed-session.js +433 -0
  125. package/dist/server/embed-session.js.map +1 -0
  126. package/dist/server/index.d.ts +2 -0
  127. package/dist/server/index.d.ts.map +1 -1
  128. package/dist/server/index.js +2 -0
  129. package/dist/server/index.js.map +1 -1
  130. package/dist/server/open-route.d.ts.map +1 -1
  131. package/dist/server/open-route.js +10 -0
  132. package/dist/server/open-route.js.map +1 -1
  133. package/dist/server/security-headers.d.ts.map +1 -1
  134. package/dist/server/security-headers.js +4 -2
  135. package/dist/server/security-headers.js.map +1 -1
  136. package/dist/shared/embed-auth.d.ts +6 -0
  137. package/dist/shared/embed-auth.d.ts.map +1 -0
  138. package/dist/shared/embed-auth.js +6 -0
  139. package/dist/shared/embed-auth.js.map +1 -0
  140. package/dist/shared/index.d.ts +1 -0
  141. package/dist/shared/index.d.ts.map +1 -1
  142. package/dist/shared/index.js +1 -0
  143. package/dist/shared/index.js.map +1 -1
  144. package/dist/templates/workspace-core/AGENTS.md +14 -5
  145. package/dist/templates/workspace-root/AGENTS.md +5 -0
  146. package/dist/templates/workspace-root/README.md +3 -0
  147. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  148. package/dist/vite/action-types-plugin.js +10 -1
  149. package/dist/vite/action-types-plugin.js.map +1 -1
  150. package/docs/content/a2a-protocol.md +5 -1
  151. package/docs/content/actions.md +19 -4
  152. package/docs/content/cli-adapters.md +5 -0
  153. package/docs/content/client.md +35 -1
  154. package/docs/content/database.md +29 -0
  155. package/docs/content/dispatch.md +7 -1
  156. package/docs/content/external-agents.md +37 -13
  157. package/docs/content/messaging.md +1 -1
  158. package/docs/content/onboarding.md +26 -0
  159. package/docs/content/template-content.md +1 -1
  160. package/docs/content/template-dispatch.md +9 -0
  161. package/docs/content/template-starter.md +2 -2
  162. package/package.json +1 -1
  163. package/src/templates/workspace-core/AGENTS.md +14 -5
  164. package/src/templates/workspace-root/AGENTS.md +5 -0
  165. package/src/templates/workspace-root/README.md +3 -0
@@ -0,0 +1,8 @@
1
+ import type { H3Event } from "h3";
2
+ import type { AuthSession } from "./auth.js";
3
+ export declare function buildEmbedStartPath(ticket: string): string;
4
+ export interface EmbedStartRouteOptions {
5
+ getExistingSession?: (event: H3Event) => Promise<AuthSession | null>;
6
+ }
7
+ export declare function createEmbedStartRouteHandler(options?: EmbedStartRouteOptions): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<Response>>;
8
+ //# sourceMappingURL=embed-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-route.d.ts","sourceRoot":"","sources":["../../src/server/embed-route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAQlC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AA0C7C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CACtE;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,GAAE,sBAA2B,2FAuCrC"}
@@ -0,0 +1,71 @@
1
+ import { defineEventHandler, getMethod, getQuery, setResponseHeader } from "h3";
2
+ import { consumeEmbedSessionTicket, normalizeEmbedTargetPath, setEmbedSessionCookie, signEmbedSessionToken, } from "./embed-session.js";
3
+ import { getConfiguredAppBasePath } from "./app-base-path.js";
4
+ import { EMBED_MODE_QUERY_PARAM, EMBED_START_PATH, EMBED_TOKEN_QUERY_PARAM, } from "../shared/embed-auth.js";
5
+ import { withCollapsedAgentSidebarParam } from "../shared/agent-sidebar-url.js";
6
+ function withConfiguredBasePath(path) {
7
+ const base = getConfiguredAppBasePath();
8
+ if (!base)
9
+ return path;
10
+ if (path === base || path.startsWith(`${base}/`))
11
+ return path;
12
+ return `${base}${path}`;
13
+ }
14
+ function appendEmbedParams(target, token) {
15
+ const url = new URL(target, "http://agent-native.invalid");
16
+ url.searchParams.set(EMBED_MODE_QUERY_PARAM, "1");
17
+ url.searchParams.set(EMBED_TOKEN_QUERY_PARAM, token);
18
+ return `${url.pathname}${url.search}${url.hash}`;
19
+ }
20
+ function redirectWithStagedCookies(event, location, status = 302) {
21
+ const headers = new Headers({ Location: location });
22
+ const staged = event.res?.headers?.getSetCookie?.() ?? [];
23
+ for (const cookie of staged)
24
+ headers.append("set-cookie", cookie);
25
+ headers.set("Referrer-Policy", "no-referrer");
26
+ return new Response("", { status, headers });
27
+ }
28
+ function textResponse(message, status) {
29
+ return new Response(message, {
30
+ status,
31
+ headers: { "Content-Type": "text/plain; charset=utf-8" },
32
+ });
33
+ }
34
+ export function buildEmbedStartPath(ticket) {
35
+ const qs = new URLSearchParams({ ticket });
36
+ return `${getConfiguredAppBasePath()}${EMBED_START_PATH}?${qs}`;
37
+ }
38
+ export function createEmbedStartRouteHandler(options = {}) {
39
+ return defineEventHandler(async (event) => {
40
+ const method = getMethod(event);
41
+ if (method !== "GET" && method !== "HEAD") {
42
+ return textResponse("Method not allowed", 405);
43
+ }
44
+ const rawTicket = getQuery(event)?.ticket;
45
+ const ticket = Array.isArray(rawTicket) ? rawTicket[0] : rawTicket;
46
+ const existingSession = await options
47
+ .getExistingSession?.(event)
48
+ .catch(() => null);
49
+ const consumed = await consumeEmbedSessionTicket(ticket, {
50
+ expectedOrgId: existingSession?.orgId ?? null,
51
+ });
52
+ if (!consumed) {
53
+ return textResponse("Invalid or expired embed session.", 401);
54
+ }
55
+ const target = normalizeEmbedTargetPath(consumed.targetPath);
56
+ if (!target) {
57
+ return textResponse("Invalid embed target.", 400);
58
+ }
59
+ const token = signEmbedSessionToken({
60
+ ownerEmail: consumed.ownerEmail,
61
+ orgId: consumed.orgId,
62
+ targetPath: target,
63
+ scope: consumed.scope,
64
+ });
65
+ setEmbedSessionCookie(event, token);
66
+ setResponseHeader(event, "Referrer-Policy", "no-referrer");
67
+ const location = withConfiguredBasePath(withCollapsedAgentSidebarParam(appendEmbedParams(target, token)));
68
+ return redirectWithStagedCookies(event, location);
69
+ });
70
+ }
71
+ //# sourceMappingURL=embed-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-route.js","sourceRoot":"","sources":["../../src/server/embed-route.ts"],"names":[],"mappings":"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","sourcesContent":["import type { H3Event } from \"h3\";\nimport { defineEventHandler, getMethod, getQuery, setResponseHeader } from \"h3\";\nimport {\n consumeEmbedSessionTicket,\n normalizeEmbedTargetPath,\n setEmbedSessionCookie,\n signEmbedSessionToken,\n} from \"./embed-session.js\";\nimport type { AuthSession } from \"./auth.js\";\nimport { getConfiguredAppBasePath } from \"./app-base-path.js\";\nimport {\n EMBED_MODE_QUERY_PARAM,\n EMBED_START_PATH,\n EMBED_TOKEN_QUERY_PARAM,\n} from \"../shared/embed-auth.js\";\nimport { withCollapsedAgentSidebarParam } from \"../shared/agent-sidebar-url.js\";\n\nfunction withConfiguredBasePath(path: string): string {\n const base = getConfiguredAppBasePath();\n if (!base) return path;\n if (path === base || path.startsWith(`${base}/`)) return path;\n return `${base}${path}`;\n}\n\nfunction appendEmbedParams(target: string, token: string): string {\n const url = new URL(target, \"http://agent-native.invalid\");\n url.searchParams.set(EMBED_MODE_QUERY_PARAM, \"1\");\n url.searchParams.set(EMBED_TOKEN_QUERY_PARAM, token);\n return `${url.pathname}${url.search}${url.hash}`;\n}\n\nfunction redirectWithStagedCookies(\n event: H3Event,\n location: string,\n status = 302,\n): Response {\n const headers = new Headers({ Location: location });\n const staged = event.res?.headers?.getSetCookie?.() ?? [];\n for (const cookie of staged) headers.append(\"set-cookie\", cookie);\n headers.set(\"Referrer-Policy\", \"no-referrer\");\n return new Response(\"\", { status, headers });\n}\n\nfunction textResponse(message: string, status: number): Response {\n return new Response(message, {\n status,\n headers: { \"Content-Type\": \"text/plain; charset=utf-8\" },\n });\n}\n\nexport function buildEmbedStartPath(ticket: string): string {\n const qs = new URLSearchParams({ ticket });\n return `${getConfiguredAppBasePath()}${EMBED_START_PATH}?${qs}`;\n}\n\nexport interface EmbedStartRouteOptions {\n getExistingSession?: (event: H3Event) => Promise<AuthSession | null>;\n}\n\nexport function createEmbedStartRouteHandler(\n options: EmbedStartRouteOptions = {},\n) {\n return defineEventHandler(async (event: H3Event) => {\n const method = getMethod(event);\n if (method !== \"GET\" && method !== \"HEAD\") {\n return textResponse(\"Method not allowed\", 405);\n }\n\n const rawTicket = getQuery(event)?.ticket;\n const ticket = Array.isArray(rawTicket) ? rawTicket[0] : rawTicket;\n const existingSession = await options\n .getExistingSession?.(event)\n .catch(() => null);\n const consumed = await consumeEmbedSessionTicket(ticket, {\n expectedOrgId: existingSession?.orgId ?? null,\n });\n if (!consumed) {\n return textResponse(\"Invalid or expired embed session.\", 401);\n }\n\n const target = normalizeEmbedTargetPath(consumed.targetPath);\n if (!target) {\n return textResponse(\"Invalid embed target.\", 400);\n }\n\n const token = signEmbedSessionToken({\n ownerEmail: consumed.ownerEmail,\n orgId: consumed.orgId,\n targetPath: target,\n scope: consumed.scope,\n });\n setEmbedSessionCookie(event, token);\n setResponseHeader(event, \"Referrer-Policy\", \"no-referrer\");\n\n const location = withConfiguredBasePath(\n withCollapsedAgentSidebarParam(appendEmbedParams(target, token)),\n );\n return redirectWithStagedCookies(event, location);\n });\n}\n"]}
@@ -0,0 +1,65 @@
1
+ import type { H3Event } from "h3";
2
+ declare const TOKEN_KIND = "agent-native-embed-session";
3
+ export interface EmbedSessionTicketInput {
4
+ ownerEmail: string;
5
+ orgId?: string | null;
6
+ targetPath: string;
7
+ scope?: string | null;
8
+ ttlSeconds?: number;
9
+ }
10
+ export interface EmbedSessionTicket {
11
+ ticket: string;
12
+ ticketHash: string;
13
+ expiresAt: number;
14
+ }
15
+ export interface ConsumeEmbedSessionTicketOptions {
16
+ expectedOrgId?: string | null;
17
+ }
18
+ export interface ConsumedEmbedSessionTicket {
19
+ ownerEmail: string;
20
+ orgId?: string;
21
+ targetPath: string;
22
+ scope?: string;
23
+ expiresAt: number;
24
+ }
25
+ export interface EmbedSessionTokenClaims {
26
+ kind: typeof TOKEN_KIND;
27
+ ownerEmail: string;
28
+ orgId?: string;
29
+ targetPath: string;
30
+ scope?: string;
31
+ iat: number;
32
+ exp: number;
33
+ }
34
+ export type VerifyEmbedSessionTokenResult = {
35
+ ok: true;
36
+ claims: EmbedSessionTokenClaims;
37
+ } | {
38
+ ok: false;
39
+ reason: string;
40
+ };
41
+ export type ResolvedEmbedSession = {
42
+ email: string;
43
+ orgId?: string;
44
+ token: string;
45
+ targetPath: string;
46
+ scope?: string;
47
+ };
48
+ export declare function requestMatchesEmbedTarget(event: H3Event, targetPath: string): boolean;
49
+ export declare function normalizeEmbedTargetPath(raw: string | undefined | null, requestOrigin?: string): string | null;
50
+ export declare function createEmbedSessionTicket(input: EmbedSessionTicketInput): Promise<EmbedSessionTicket>;
51
+ export declare function consumeEmbedSessionTicket(ticket: string | undefined | null, options?: ConsumeEmbedSessionTicketOptions): Promise<ConsumedEmbedSessionTicket | null>;
52
+ export declare function signEmbedSessionToken(input: {
53
+ ownerEmail: string;
54
+ orgId?: string | null;
55
+ targetPath: string;
56
+ scope?: string | null;
57
+ ttlSeconds?: number;
58
+ }): string;
59
+ export declare function verifyEmbedSessionToken(token: string | undefined | null): VerifyEmbedSessionTokenResult;
60
+ export declare function setEmbedSessionCookie(event: H3Event, token: string): void;
61
+ export declare function resolveEmbedSessionFromRequest(event: H3Event): Promise<ResolvedEmbedSession | null>;
62
+ export declare function requestHasEmbedAuthMarker(event: H3Event): boolean;
63
+ export declare function isEmbedModeRequest(event: H3Event): boolean;
64
+ export {};
65
+ //# sourceMappingURL=embed-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed-session.d.ts","sourceRoot":"","sources":["../../src/server/embed-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,433 @@
1
+ import crypto from "node:crypto";
2
+ import { getCookie, getHeader, getQuery, setCookie, setResponseHeader, } from "h3";
3
+ import { getDbExec, intType } from "../db/client.js";
4
+ import { getWorkspaceA2ADerivedSecret } from "./derived-secret.js";
5
+ import { getConfiguredAppBasePath } from "./app-base-path.js";
6
+ import { EMBED_MODE_QUERY_PARAM, EMBED_SESSION_COOKIE, EMBED_TARGET_HEADER, EMBED_TOKEN_QUERY_PARAM, } from "../shared/embed-auth.js";
7
+ const TOKEN_KIND = "agent-native-embed-session";
8
+ const DEFAULT_TOKEN_TTL_SECONDS = 60 * 60;
9
+ const DEFAULT_TICKET_TTL_SECONDS = 5 * 60;
10
+ const CONTROL_CHARS = new RegExp("[\\u0000-\\u001f\\u007f]");
11
+ const OPEN_ROUTE_PATH = "/_agent-native/open";
12
+ let _initPromise;
13
+ let _devSigningKey;
14
+ async function ensureTable() {
15
+ if (!_initPromise) {
16
+ _initPromise = (async () => {
17
+ const client = getDbExec();
18
+ await client.execute(`
19
+ CREATE TABLE IF NOT EXISTS agent_native_embed_tickets (
20
+ ticket_hash TEXT PRIMARY KEY,
21
+ owner_email TEXT NOT NULL,
22
+ org_id TEXT,
23
+ target_path TEXT NOT NULL,
24
+ scope TEXT,
25
+ created_at ${intType()} NOT NULL,
26
+ expires_at ${intType()} NOT NULL,
27
+ consumed_at ${intType()}
28
+ )
29
+ `);
30
+ })().catch((err) => {
31
+ _initPromise = undefined;
32
+ throw err;
33
+ });
34
+ }
35
+ return _initPromise;
36
+ }
37
+ function getSigningKey() {
38
+ const secret = process.env.OAUTH_STATE_SECRET ||
39
+ process.env.BETTER_AUTH_SECRET ||
40
+ getWorkspaceA2ADerivedSecret("short-lived-token");
41
+ if (secret)
42
+ return secret;
43
+ if (process.env.NODE_ENV === "production") {
44
+ throw new Error("Embed session signing requires a server secret. Set OAUTH_STATE_SECRET, BETTER_AUTH_SECRET, or A2A_SECRET in production workspace deploys.");
45
+ }
46
+ if (!_devSigningKey) {
47
+ _devSigningKey = crypto.randomBytes(32).toString("hex");
48
+ }
49
+ return _devSigningKey;
50
+ }
51
+ function base64UrlEncode(buf) {
52
+ const b = typeof buf === "string" ? Buffer.from(buf, "utf8") : buf;
53
+ return b
54
+ .toString("base64")
55
+ .replace(/\+/g, "-")
56
+ .replace(/\//g, "_")
57
+ .replace(/=+$/g, "");
58
+ }
59
+ function base64UrlDecode(input) {
60
+ const padded = input + "=".repeat((4 - (input.length % 4)) % 4);
61
+ return Buffer.from(padded.replace(/-/g, "+").replace(/_/g, "/"), "base64");
62
+ }
63
+ function signPayload(payload) {
64
+ return base64UrlEncode(crypto.createHmac("sha256", getSigningKey()).update(payload).digest());
65
+ }
66
+ function hashTicket(ticket) {
67
+ return crypto.createHash("sha256").update(ticket).digest("hex");
68
+ }
69
+ function numberOrNull(value) {
70
+ if (value == null)
71
+ return null;
72
+ const n = Number(value);
73
+ return Number.isFinite(n) ? n : null;
74
+ }
75
+ function stringOrUndefined(value) {
76
+ return typeof value === "string" && value ? value : undefined;
77
+ }
78
+ function stripConfiguredBasePath(pathname) {
79
+ const base = getConfiguredAppBasePath();
80
+ if (!base)
81
+ return pathname;
82
+ if (pathname === base)
83
+ return "/";
84
+ if (pathname.startsWith(`${base}/`))
85
+ return pathname.slice(base.length) || "/";
86
+ return pathname;
87
+ }
88
+ function pathnameFromPath(path) {
89
+ const normalized = normalizeEmbedTargetPath(path);
90
+ if (!normalized)
91
+ return null;
92
+ try {
93
+ return new URL(normalized, "http://agent-native.invalid").pathname;
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ function safeOpenRouteTargetPathname(targetPath) {
100
+ let url;
101
+ try {
102
+ url = new URL(targetPath, "http://agent-native.invalid");
103
+ }
104
+ catch {
105
+ return null;
106
+ }
107
+ if (url.pathname !== OPEN_ROUTE_PATH) {
108
+ return null;
109
+ }
110
+ const to = normalizeEmbedTargetPath(url.searchParams.get("to"));
111
+ if (to)
112
+ return pathnameFromPath(to);
113
+ const view = url.searchParams.get("view")?.trim();
114
+ if (!view || CONTROL_CHARS.test(view))
115
+ return null;
116
+ const viewPath = view.startsWith("/") ? view : `/${view}`;
117
+ return pathnameFromPath(viewPath);
118
+ }
119
+ function allowedEmbedTargetPathnames(targetPath) {
120
+ const allowed = new Set();
121
+ const direct = pathnameFromPath(targetPath);
122
+ if (direct)
123
+ allowed.add(direct);
124
+ const openTarget = safeOpenRouteTargetPathname(targetPath);
125
+ if (openTarget)
126
+ allowed.add(openTarget);
127
+ return allowed;
128
+ }
129
+ function requestPathname(event) {
130
+ const raw = event.path ??
131
+ event.node?.req?.url ??
132
+ event.req?.url ??
133
+ event.url?.toString?.() ??
134
+ "/";
135
+ try {
136
+ const pathname = new URL(raw, "http://agent-native.invalid").pathname;
137
+ return stripConfiguredBasePath(pathname);
138
+ }
139
+ catch {
140
+ return null;
141
+ }
142
+ }
143
+ function headerTargetPathname(event) {
144
+ const direct = event.request?.headers?.get?.(EMBED_TARGET_HEADER) ??
145
+ event.headers?.get?.(EMBED_TARGET_HEADER) ??
146
+ event.node?.req?.headers?.[EMBED_TARGET_HEADER] ??
147
+ event.node?.req?.headers?.[EMBED_TARGET_HEADER.toLowerCase()];
148
+ if (typeof direct === "string")
149
+ return pathnameFromPath(direct);
150
+ try {
151
+ const raw = getHeader(event, EMBED_TARGET_HEADER);
152
+ return typeof raw === "string" ? pathnameFromPath(raw) : null;
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
158
+ export function requestMatchesEmbedTarget(event, targetPath) {
159
+ const allowed = allowedEmbedTargetPathnames(targetPath);
160
+ if (allowed.size === 0)
161
+ return false;
162
+ const current = requestPathname(event);
163
+ if (current && allowed.has(current))
164
+ return true;
165
+ const headerTarget = headerTargetPathname(event);
166
+ return !!headerTarget && allowed.has(headerTarget);
167
+ }
168
+ export function normalizeEmbedTargetPath(raw, requestOrigin) {
169
+ const value = String(raw ?? "").trim();
170
+ if (!value || CONTROL_CHARS.test(value))
171
+ return null;
172
+ let path = value;
173
+ try {
174
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value)) {
175
+ const parsed = new URL(value);
176
+ if (requestOrigin) {
177
+ const expected = new URL(requestOrigin);
178
+ if (parsed.origin !== expected.origin)
179
+ return null;
180
+ }
181
+ const base = getConfiguredAppBasePath();
182
+ if (base &&
183
+ parsed.pathname !== base &&
184
+ !parsed.pathname.startsWith(`${base}/`)) {
185
+ return null;
186
+ }
187
+ path = `${parsed.pathname}${parsed.search}${parsed.hash}`;
188
+ }
189
+ }
190
+ catch {
191
+ return null;
192
+ }
193
+ if (!path.startsWith("/"))
194
+ path = `/${path}`;
195
+ if (path.startsWith("//") || path.startsWith("/\\"))
196
+ return null;
197
+ if (/^\/[a-z][a-z0-9+.-]*:/i.test(path))
198
+ return null;
199
+ return stripConfiguredBasePath(path);
200
+ }
201
+ export async function createEmbedSessionTicket(input) {
202
+ const ownerEmail = input.ownerEmail.trim();
203
+ if (!ownerEmail)
204
+ throw new Error("Embed session ticket requires ownerEmail.");
205
+ const targetPath = normalizeEmbedTargetPath(input.targetPath);
206
+ if (!targetPath)
207
+ throw new Error("Embed session ticket requires a safe path.");
208
+ await ensureTable();
209
+ const ticket = crypto.randomBytes(32).toString("base64url");
210
+ const ticketHash = hashTicket(ticket);
211
+ const now = Date.now();
212
+ const ttlSeconds = input.ttlSeconds ?? DEFAULT_TICKET_TTL_SECONDS;
213
+ const expiresAt = now + Math.max(1, ttlSeconds) * 1000;
214
+ await getDbExec().execute({
215
+ sql: "INSERT INTO agent_native_embed_tickets " +
216
+ "(ticket_hash, owner_email, org_id, target_path, scope, created_at, expires_at, consumed_at) " +
217
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
218
+ args: [
219
+ ticketHash,
220
+ ownerEmail,
221
+ input.orgId ?? null,
222
+ targetPath,
223
+ input.scope ?? null,
224
+ now,
225
+ expiresAt,
226
+ null,
227
+ ],
228
+ });
229
+ return { ticket, ticketHash, expiresAt };
230
+ }
231
+ export async function consumeEmbedSessionTicket(ticket, options = {}) {
232
+ if (!ticket)
233
+ return null;
234
+ await ensureTable();
235
+ const ticketHash = hashTicket(ticket);
236
+ const now = Date.now();
237
+ const { rows } = await getDbExec().execute({
238
+ sql: "SELECT ticket_hash, owner_email, org_id, target_path, scope, expires_at, consumed_at " +
239
+ "FROM agent_native_embed_tickets WHERE ticket_hash = ?",
240
+ args: [ticketHash],
241
+ });
242
+ if (rows.length === 0)
243
+ return null;
244
+ const row = rows[0];
245
+ const expiresAt = numberOrNull(row.expires_at ?? row.expiresAt);
246
+ const consumedAt = numberOrNull(row.consumed_at ?? row.consumedAt);
247
+ const orgId = stringOrUndefined(row.org_id ?? row.orgId);
248
+ if (consumedAt != null)
249
+ return null;
250
+ if (expiresAt != null && expiresAt < now)
251
+ return null;
252
+ if (options.expectedOrgId && orgId && orgId !== options.expectedOrgId) {
253
+ return null;
254
+ }
255
+ const result = await getDbExec().execute({
256
+ sql: "UPDATE agent_native_embed_tickets SET consumed_at = ? " +
257
+ "WHERE ticket_hash = ? AND consumed_at IS NULL",
258
+ args: [now, ticketHash],
259
+ });
260
+ if (result.rowsAffected === 0)
261
+ return null;
262
+ const targetPath = normalizeEmbedTargetPath(stringOrUndefined(row.target_path ?? row.targetPath));
263
+ const ownerEmail = stringOrUndefined(row.owner_email ?? row.ownerEmail);
264
+ if (!targetPath || !ownerEmail || expiresAt == null)
265
+ return null;
266
+ return {
267
+ ownerEmail,
268
+ ...(orgId ? { orgId } : {}),
269
+ targetPath,
270
+ ...(stringOrUndefined(row.scope)
271
+ ? { scope: stringOrUndefined(row.scope) }
272
+ : {}),
273
+ expiresAt,
274
+ };
275
+ }
276
+ export function signEmbedSessionToken(input) {
277
+ const targetPath = normalizeEmbedTargetPath(input.targetPath) ?? "/";
278
+ const now = Math.floor(Date.now() / 1000);
279
+ const ttl = Math.max(1, input.ttlSeconds ?? DEFAULT_TOKEN_TTL_SECONDS);
280
+ const claims = {
281
+ kind: TOKEN_KIND,
282
+ ownerEmail: input.ownerEmail,
283
+ targetPath,
284
+ iat: now,
285
+ exp: now + ttl,
286
+ };
287
+ if (input.orgId)
288
+ claims.orgId = input.orgId;
289
+ if (input.scope)
290
+ claims.scope = input.scope;
291
+ const payload = base64UrlEncode(JSON.stringify(claims));
292
+ return `${payload}.${signPayload(payload)}`;
293
+ }
294
+ export function verifyEmbedSessionToken(token) {
295
+ if (!token || typeof token !== "string") {
296
+ return { ok: false, reason: "missing" };
297
+ }
298
+ const parts = token.split(".");
299
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
300
+ return { ok: false, reason: "shape" };
301
+ }
302
+ const [payload, signature] = parts;
303
+ const expected = signPayload(payload);
304
+ const sig = Buffer.from(signature);
305
+ const exp = Buffer.from(expected);
306
+ if (sig.length !== exp.length || !crypto.timingSafeEqual(sig, exp)) {
307
+ return { ok: false, reason: "signature" };
308
+ }
309
+ let claims;
310
+ try {
311
+ claims = JSON.parse(base64UrlDecode(payload).toString("utf8"));
312
+ }
313
+ catch {
314
+ return { ok: false, reason: "payload" };
315
+ }
316
+ if (!claims ||
317
+ claims.kind !== TOKEN_KIND ||
318
+ typeof claims.ownerEmail !== "string" ||
319
+ !claims.ownerEmail ||
320
+ typeof claims.exp !== "number" ||
321
+ !Number.isFinite(claims.exp)) {
322
+ return { ok: false, reason: "claims" };
323
+ }
324
+ if (claims.exp < Math.floor(Date.now() / 1000)) {
325
+ return { ok: false, reason: "expired" };
326
+ }
327
+ claims.targetPath = normalizeEmbedTargetPath(claims.targetPath) ?? "/";
328
+ return { ok: true, claims };
329
+ }
330
+ function isHttpsRequest(event) {
331
+ try {
332
+ const xfProto = getHeader(event, "x-forwarded-proto");
333
+ if (xfProto && String(xfProto).split(",")[0].trim() === "https") {
334
+ return true;
335
+ }
336
+ const url = event.url?.toString?.() ?? "";
337
+ if (url.startsWith("https://"))
338
+ return true;
339
+ const appUrl = process.env.APP_URL || process.env.BETTER_AUTH_URL || "";
340
+ if (appUrl.startsWith("https://"))
341
+ return true;
342
+ }
343
+ catch {
344
+ // ignore
345
+ }
346
+ return false;
347
+ }
348
+ function cookieDomainAttrs() {
349
+ const domain = process.env.COOKIE_DOMAIN?.trim();
350
+ return domain ? { domain } : {};
351
+ }
352
+ function crossSiteCookieAttrs(event) {
353
+ return isHttpsRequest(event)
354
+ ? { sameSite: "none", secure: true, partitioned: true }
355
+ : { sameSite: "lax", secure: false };
356
+ }
357
+ export function setEmbedSessionCookie(event, token) {
358
+ setCookie(event, EMBED_SESSION_COOKIE, token, {
359
+ httpOnly: true,
360
+ ...crossSiteCookieAttrs(event),
361
+ ...cookieDomainAttrs(),
362
+ path: "/",
363
+ maxAge: DEFAULT_TOKEN_TTL_SECONDS,
364
+ });
365
+ }
366
+ function bearerToken(event) {
367
+ const auth = getHeader(event, "authorization");
368
+ if (!auth)
369
+ return undefined;
370
+ const match = /^Bearer\s+(.+)$/i.exec(String(auth).trim());
371
+ return match?.[1]?.trim();
372
+ }
373
+ function queryToken(event) {
374
+ const raw = getQuery(event)?.[EMBED_TOKEN_QUERY_PARAM];
375
+ return Array.isArray(raw) ? raw[0] : raw;
376
+ }
377
+ export async function resolveEmbedSessionFromRequest(event) {
378
+ const candidates = [
379
+ { token: queryToken(event), source: "query" },
380
+ { token: bearerToken(event), source: "bearer" },
381
+ { token: getCookie(event, EMBED_SESSION_COOKIE), source: "cookie" },
382
+ ];
383
+ for (const candidate of candidates) {
384
+ const verified = verifyEmbedSessionToken(candidate.token);
385
+ if (!verified.ok)
386
+ continue;
387
+ if (!requestMatchesEmbedTarget(event, verified.claims.targetPath)) {
388
+ continue;
389
+ }
390
+ if (candidate.source === "query" && candidate.token) {
391
+ setEmbedSessionCookie(event, candidate.token);
392
+ setResponseHeader(event, "Referrer-Policy", "no-referrer");
393
+ }
394
+ return {
395
+ email: verified.claims.ownerEmail,
396
+ token: candidate.token,
397
+ targetPath: verified.claims.targetPath,
398
+ ...(verified.claims.orgId ? { orgId: verified.claims.orgId } : {}),
399
+ ...(verified.claims.scope ? { scope: verified.claims.scope } : {}),
400
+ };
401
+ }
402
+ return null;
403
+ }
404
+ export function requestHasEmbedAuthMarker(event) {
405
+ try {
406
+ const q = getQuery(event) ?? {};
407
+ const queryToken = Array.isArray(q[EMBED_TOKEN_QUERY_PARAM])
408
+ ? q[EMBED_TOKEN_QUERY_PARAM][0]
409
+ : q[EMBED_TOKEN_QUERY_PARAM];
410
+ const cookieToken = getCookie(event, EMBED_SESSION_COOKIE);
411
+ for (const token of [queryToken, cookieToken]) {
412
+ const verified = verifyEmbedSessionToken(token);
413
+ if (verified.ok &&
414
+ requestMatchesEmbedTarget(event, verified.claims.targetPath)) {
415
+ return true;
416
+ }
417
+ }
418
+ }
419
+ catch {
420
+ // ignore
421
+ }
422
+ return false;
423
+ }
424
+ export function isEmbedModeRequest(event) {
425
+ try {
426
+ const q = getQuery(event) ?? {};
427
+ return (q[EMBED_MODE_QUERY_PARAM] === "1" || q[EMBED_MODE_QUERY_PARAM] === "true");
428
+ }
429
+ catch {
430
+ return false;
431
+ }
432
+ }
433
+ //# sourceMappingURL=embed-session.js.map