@agent-native/core 0.12.39 → 0.12.40

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.
@@ -2991,13 +2991,65 @@ export function createAgentChatPlugin(options) {
2991
2991
  : undefined;
2992
2992
  return buildRuntimeContextPrompt({ timezone });
2993
2993
  };
2994
+ // Chat-in-browser-on-localdev is the one surface where the agent must
2995
+ // not edit code: source-file edits trigger Vite HMR / page reloads and
2996
+ // kill the chat session mid-run. The client sends an
2997
+ // `x-agent-native-surface` header (desktop | frame | browser); we fall
2998
+ // back to UA + Host inspection when the header is missing (older clients,
2999
+ // server-to-server callers, etc.). Returning true forces the prod
3000
+ // handler (no shell / no fs) AND injects a redirect-prompt block telling
3001
+ // the agent to point users at Desktop / Claude Code / Codex / Builder.io.
3002
+ const isChatInBrowserOnLocalDev = (event) => {
3003
+ const surface = (getHeader(event, "x-agent-native-surface") || "").toLowerCase();
3004
+ const ua = getHeader(event, "user-agent") || "";
3005
+ const isDesktop = surface === "desktop" || /AgentNativeDesktop/i.test(ua);
3006
+ if (isDesktop)
3007
+ return false;
3008
+ if (surface === "frame")
3009
+ return false;
3010
+ const host = (getHeader(event, "host") || "").toLowerCase();
3011
+ const hostname = host.split(":")[0] ?? "";
3012
+ const isLocal = hostname === "localhost" ||
3013
+ hostname === "127.0.0.1" ||
3014
+ hostname === "::1" ||
3015
+ hostname === "[::1]";
3016
+ if (!isLocal)
3017
+ return false;
3018
+ // No header from an older client + non-desktop UA: be conservative and
3019
+ // only trip on plain browser UAs. Treat unknown clients as safe (frame
3020
+ // / desktop / scripting) so we don't break their tool access.
3021
+ if (!surface) {
3022
+ return /Mozilla\/|Chrome\/|Safari\/|Firefox\/|Edg\//i.test(ua);
3023
+ }
3024
+ return surface === "browser";
3025
+ };
3026
+ const CHAT_IN_BROWSER_LOCAL_DEV_PROMPT = `
3027
+
3028
+ <chat-in-browser-on-localdev>
3029
+ This chat is running in a plain browser tab on localhost. Source-code edits would trigger Vite HMR or a full page reload, which kills the chat session mid-run, so source-code work cannot happen on this surface.
3030
+
3031
+ When the user asks for ANY of the following — add a feature, edit a component, fix a bug in the app itself, change styles, add a route, scaffold a new app, run shell commands that modify code, or anything else that requires touching source files:
3032
+
3033
+ 1. Do NOT call \`connect-builder\`, \`scaffold-workspace-app\`, \`start-workspace-app-creation\`, or any other tool that creates or edits source.
3034
+ 2. Do NOT write code, list files, propose patches, or describe what you would change.
3035
+ 3. Reply with one short message saying chat-in-browser on localhost can't edit code (page reloads kill the session) and offer these alternatives, in this order:
3036
+ - **Agent Native Desktop** — https://www.agent-native.com/download (recommended; same chat, no reload risk)
3037
+ - **Claude Code** — \`claude\` in the project directory
3038
+ - **Codex** — \`codex\` in the project directory
3039
+ - **Builder.io** — open the project in Builder for cloud-based code changes
3040
+
3041
+ Non-code requests are still fine on this surface — read data, navigate the UI, summarize, search, create/update extensions (sandboxed Alpine.js mini-apps stored in SQL), and call template actions. The restriction is specifically about editing the app's own source files.
3042
+ </chat-in-browser-on-localdev>`;
2994
3043
  const prodHandler = createProductionAgentHandler({
2995
3044
  actions: leanPrompt ? leanActions : prodActions,
2996
3045
  systemPrompt: async (event) => {
2997
3046
  const { owner, extra } = await prepareRun(event);
2998
3047
  const runtimeContext = runtimeContextForEvent(event);
3048
+ const browserLocalDev = isChatInBrowserOnLocalDev(event)
3049
+ ? CHAT_IN_BROWSER_LOCAL_DEV_PROMPT
3050
+ : "";
2999
3051
  if (leanPrompt) {
3000
- return setSystemPromptOnContext(leanBasePrompt + runtimeContext + extra);
3052
+ return setSystemPromptOnContext(leanBasePrompt + runtimeContext + browserLocalDev + extra);
3001
3053
  }
3002
3054
  const resources = await loadResourcesForPrompt(owner, lazyContext);
3003
3055
  // In lazy context mode, skip embedding the full schema — the agent
@@ -3005,7 +3057,12 @@ export function createAgentChatPlugin(options) {
3005
3057
  const schemaBlock = lazyContext
3006
3058
  ? ""
3007
3059
  : await buildSchemaBlock(owner, false);
3008
- return setSystemPromptOnContext(basePrompt + runtimeContext + resources + schemaBlock + extra);
3060
+ return setSystemPromptOnContext(basePrompt +
3061
+ runtimeContext +
3062
+ resources +
3063
+ schemaBlock +
3064
+ browserLocalDev +
3065
+ extra);
3009
3066
  },
3010
3067
  model: options?.model,
3011
3068
  apiKey: options?.apiKey,
@@ -4022,9 +4079,15 @@ export function createAgentChatPlugin(options) {
4022
4079
  orgId: resolvedOrgId,
4023
4080
  timezone,
4024
4081
  }, () => {
4082
+ // Chat-in-browser on localhost can't host code edits — Vite HMR
4083
+ // and full reloads would kill the chat mid-run. Force the prod
4084
+ // handler (no shell / no fs); the prompt block injected by
4085
+ // `prodHandler.systemPrompt` then steers the agent to suggest
4086
+ // Desktop / Claude Code / Codex / Builder.io instead.
4087
+ const browserLocalDev = isChatInBrowserOnLocalDev(event);
4025
4088
  const handler = ownerContext.anonymous && anonymousHandler
4026
4089
  ? anonymousHandler
4027
- : currentDevMode && devHandler
4090
+ : !browserLocalDev && currentDevMode && devHandler
4028
4091
  ? devHandler
4029
4092
  : prodHandler;
4030
4093
  return handler(event);