@agent-native/core 0.164.12 → 0.164.15

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 (43) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/content/actions/_database-source-utils.ts +25 -2
  3. package/corpus/templates/content/actions/_database-utils.ts +2 -0
  4. package/corpus/templates/content/actions/_local-folder-source.ts +186 -2
  5. package/corpus/templates/content/actions/connect-local-folder-source.ts +23 -8
  6. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +3 -3
  7. package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +2 -2
  8. package/corpus/templates/content/actions/sync-local-folder-source.ts +130 -12
  9. package/corpus/templates/content/app/components/LocalFolderLiveSync.tsx +77 -0
  10. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +354 -8
  11. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +23 -1
  12. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +78 -1
  13. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +36 -0
  14. package/corpus/templates/content/app/components/editor/local-source-write-state.ts +52 -0
  15. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +244 -6
  16. package/corpus/templates/content/app/components/sidebar/local-source-hierarchy.ts +189 -0
  17. package/corpus/templates/content/app/hooks/use-create-page.ts +26 -4
  18. package/corpus/templates/content/app/hooks/use-documents.ts +83 -0
  19. package/corpus/templates/content/app/i18n-data.ts +79 -0
  20. package/corpus/templates/content/app/lib/desktop-content-files.ts +57 -1
  21. package/corpus/templates/content/app/lib/local-content-source-files.ts +210 -34
  22. package/corpus/templates/content/app/lib/local-folder-live-sync.ts +191 -0
  23. package/corpus/templates/content/app/root.tsx +2 -1
  24. package/corpus/templates/content/app/routes/_app.local-files.tsx +103 -38
  25. package/corpus/templates/content/docs/product/capabilities/content.source.file-folder.md +2 -2
  26. package/corpus/templates/content/docs/product/features/content.feature.bring-your-local-work.md +3 -3
  27. package/corpus/templates/content/docs/product/roadmap.md +2 -2
  28. package/corpus/templates/content/docs/solutions/2026-08-18-content-navigation-coherence-shape.md +482 -0
  29. package/corpus/templates/content/shared/api.ts +25 -0
  30. package/dist/app-config/auth.d.ts +4 -0
  31. package/dist/app-config/auth.js +7 -0
  32. package/dist/app-config/schema.d.ts +3 -0
  33. package/dist/app-config/schema.js +2 -0
  34. package/dist/cli/code-agent-executor.js +6 -1
  35. package/dist/cli/code-agent-mcp-config.d.ts +2 -2
  36. package/dist/cli/code-agent-mcp-config.js +34 -9
  37. package/dist/client/org/OrgSwitcher.js +8 -4
  38. package/dist/collab/routes.d.ts +1 -1
  39. package/dist/mcp-client/config.d.ts +11 -0
  40. package/dist/mcp-client/config.js +33 -26
  41. package/dist/resources/handlers.d.ts +2 -2
  42. package/dist/server/auth.js +15 -1
  43. package/package.json +1 -1
@@ -7,6 +7,7 @@ import { setBrowserDemoModeEnabled } from "../../demo/browser-state.js";
7
7
  import { shouldOfferWorkspace } from "../../org/workspace-url.js";
8
8
  import { agentNativePath } from "../api-path.js";
9
9
  import { useT } from "../i18n.js";
10
+ import { buildSignInReturnHref } from "../require-session.js";
10
11
  import { useDemoModeStatus } from "../use-demo-mode-status.js";
11
12
  import { notifySessionInvalidated, useSession } from "../use-session.js";
12
13
  import { useOrg, useSwitchOrg, useCreateOrg, useInviteMember, useAcceptInvitation, useJoinByDomain, } from "./hooks.js";
@@ -142,16 +143,19 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact,
142
143
  return;
143
144
  setSigningOut(true);
144
145
  try {
145
- await fetch(agentNativePath("/_agent-native/auth/logout"), {
146
+ const response = await fetch(agentNativePath("/_agent-native/auth/logout"), {
146
147
  method: "POST",
147
148
  credentials: "include",
148
149
  });
150
+ if (!response.ok) {
151
+ console.warn("Logout request returned an error before sign-in", response.status);
152
+ }
149
153
  }
150
- catch {
151
- /* fall through to reload — server may already have cleared the cookie */
154
+ catch (error) {
155
+ console.warn("Unable to complete logout request before sign-in", error);
152
156
  }
153
157
  notifySessionInvalidated();
154
- window.location.reload();
158
+ window.location.replace(buildSignInReturnHref());
155
159
  };
156
160
  if (!org) {
157
161
  return reserveSpace && isLoading ? (_jsx(OrgSwitcherLoadingPlaceholder, { className: className })) : null;
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- error: string;
30
29
  ok?: undefined;
30
+ error: string;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -60,12 +60,23 @@ export interface McpConfig {
60
60
  /** Where the config was loaded from (workspace root path, app path, or "env") */
61
61
  source?: string;
62
62
  }
63
+ export interface DesktopChildComputerMcpServer {
64
+ id: string;
65
+ config: McpHttpServerConfig;
66
+ }
63
67
  /**
64
68
  * Load MCP configuration.
65
69
  *
66
70
  * @param startDir - Directory to start the upward search from (defaults to cwd)
67
71
  */
68
72
  export declare function loadMcpConfig(startDir?: string): McpConfig | null;
73
+ /**
74
+ * The desktop process supplies this configuration only to a child it spawned
75
+ * for a specific Agent run. Raw MCP config cannot opt into this trust path:
76
+ * the explicit child gate, loopback URL, and strong per-run bearer are all
77
+ * required. Existing user servers always win on key collisions.
78
+ */
79
+ export declare function resolveDesktopChildComputerMcpServer(existingServers: Record<string, McpServerConfig>, environment?: NodeJS.ProcessEnv): DesktopChildComputerMcpServer | null;
69
80
  /**
70
81
  * Auto-detect the claude-in-chrome MCP server if it's installed but no
71
82
  * config file exists. Gated by `AGENT_NATIVE_DISABLE_MCP_AUTODETECT`.
@@ -96,39 +96,46 @@ export function loadMcpConfig(startDir) {
96
96
  * the explicit child gate, loopback URL, and strong per-run bearer are all
97
97
  * required. Existing user servers always win on key collisions.
98
98
  */
99
- function mergeDesktopChildComputerConfig(base) {
100
- if (process.env.AGENT_NATIVE_DESKTOP_CHILD !== "1")
101
- return base;
102
- const url = process.env.AGENT_NATIVE_DESKTOP_COMPUTER_MCP_URL?.trim();
103
- const token = process.env.AGENT_NATIVE_DESKTOP_COMPUTER_MCP_TOKEN?.trim();
99
+ export function resolveDesktopChildComputerMcpServer(existingServers, environment = process.env) {
100
+ if (environment.AGENT_NATIVE_DESKTOP_CHILD !== "1")
101
+ return null;
102
+ const url = environment.AGENT_NATIVE_DESKTOP_COMPUTER_MCP_URL?.trim();
103
+ const token = environment.AGENT_NATIVE_DESKTOP_COMPUTER_MCP_TOKEN?.trim();
104
104
  if (!url || !token || !/^[A-Za-z0-9_-]{32,}$/.test(token))
105
- return base;
106
- try {
107
- const parsed = new URL(url);
108
- if (parsed.protocol !== "http:" ||
109
- parsed.hostname !== "127.0.0.1" ||
110
- parsed.pathname !== "/mcp" ||
111
- parsed.username ||
112
- parsed.password) {
113
- return base;
114
- }
115
- }
116
- catch {
117
- return base;
105
+ return null;
106
+ if (!URL.canParse(url))
107
+ return null;
108
+ const parsed = new URL(url);
109
+ if (parsed.protocol !== "http:" ||
110
+ parsed.hostname !== "127.0.0.1" ||
111
+ parsed.pathname !== "/mcp" ||
112
+ parsed.username ||
113
+ parsed.password) {
114
+ return null;
118
115
  }
119
- const servers = { ...(base?.servers ?? {}) };
120
116
  let serverId = DESKTOP_COMPUTER_SERVER_ID;
121
- for (let suffix = 2; servers[serverId]; suffix += 1) {
117
+ for (let suffix = 2; existingServers[serverId]; suffix += 1) {
122
118
  serverId = `${DESKTOP_COMPUTER_SERVER_ID}-${suffix}`;
123
119
  }
124
- servers[serverId] = {
125
- type: "http",
126
- url,
127
- headers: { Authorization: `Bearer ${token}` },
128
- description: "Authenticated computer control for this Agent Native desktop task",
120
+ return {
121
+ id: serverId,
122
+ config: {
123
+ type: "http",
124
+ url,
125
+ headers: { Authorization: `Bearer ${token}` },
126
+ description: "Authenticated computer control for this Agent Native desktop task",
127
+ },
129
128
  };
129
+ }
130
+ function mergeDesktopChildComputerConfig(base) {
131
+ const desktopServer = resolveDesktopChildComputerMcpServer(base?.servers ?? {});
132
+ if (!desktopServer)
133
+ return base;
130
134
  return {
131
- servers,
135
+ servers: {
136
+ ...(base?.servers ?? {}),
137
+ [desktopServer.id]: desktopServer.config,
138
+ },
132
139
  source: base?.source ? `${base.source}+desktop-child` : "desktop-child",
133
140
  };
134
141
  }
@@ -51,8 +51,8 @@ export declare function handleDeleteResource(event: any): Promise<{
51
51
  error: string;
52
52
  ok?: undefined;
53
53
  } | {
54
- ok: boolean;
55
54
  error?: undefined;
55
+ ok: boolean;
56
56
  }>;
57
57
  /** POST /_agent-native/resources/upload — upload a file as a resource */
58
58
  export declare function handleUploadResource(event: any): Promise<import("./store.js").Resource | {
@@ -73,10 +73,10 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
73
73
  runId: string | null;
74
74
  expiresAt: number | null;
75
75
  metadata: string | null;
76
+ error?: undefined;
76
77
  url: string;
77
78
  provider: string;
78
79
  storageSetupRequired?: undefined;
79
- error?: undefined;
80
80
  } | {
81
81
  error: string;
82
82
  storageSetupRequired: boolean;
@@ -405,6 +405,8 @@ export function isLoopbackRequest(event) {
405
405
  async function readDesktopSsoSafely(event) {
406
406
  if (process.env.NODE_ENV === "production")
407
407
  return null;
408
+ if (getAppConfig().auth.disableDesktopSsoFallbackInDevelopment)
409
+ return null;
408
410
  if (!isElectronRequest(event))
409
411
  return null;
410
412
  if (!isLoopbackRequest(event))
@@ -1242,7 +1244,7 @@ export function prepareDesktopOAuthBrowserBinding(event) {
1242
1244
  if (!binding || !/^[A-Za-z0-9_-]{43}$/.test(binding)) {
1243
1245
  binding = crypto.randomBytes(32).toString("base64url");
1244
1246
  setCookie(event, DESKTOP_OAUTH_BROWSER_BINDING_COOKIE, binding, {
1245
- ...crossSiteCookieAttrs(event),
1247
+ ...desktopOAuthBrowserBindingCookieAttrs(event),
1246
1248
  httpOnly: true,
1247
1249
  path: "/",
1248
1250
  maxAge: Math.floor(DESKTOP_EXCHANGE_TTL_MS / 1_000),
@@ -2810,6 +2812,18 @@ function crossSiteCookieAttrs(event) {
2810
2812
  ? { sameSite: "none", secure: true, partitioned: true }
2811
2813
  : { sameSite: "lax", secure: false };
2812
2814
  }
2815
+ /**
2816
+ * The binding cookie is set before navigating to Google and read after the
2817
+ * provider redirects back. A partitioned cookie uses the top-level site from
2818
+ * the bootstrap request, so it is unavailable when the callback starts from
2819
+ * Google's top-level site. Keep this host-scoped cookie unpartitioned while
2820
+ * retaining the cross-site and transport protections required by the flow.
2821
+ */
2822
+ function desktopOAuthBrowserBindingCookieAttrs(event) {
2823
+ return isHttpsRequest(event)
2824
+ ? { sameSite: "none", secure: true }
2825
+ : { sameSite: "lax", secure: false };
2826
+ }
2813
2827
  function setFirstRunOnboardingCookie(event) {
2814
2828
  setCookie(event, FIRST_RUN_ONBOARDING_COOKIE, "1", {
2815
2829
  ...crossSiteCookieAttrs(event),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.164.12",
3
+ "version": "0.164.15",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {