@agent-native/core 0.75.1 → 0.75.4

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 (38) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +76 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/agent/durable-background.ts +54 -0
  5. package/corpus/core/src/agent/production-agent.ts +15 -3
  6. package/corpus/core/src/cli/sync-builder-starter-manifest.ts +36 -12
  7. package/corpus/core/src/deploy/build.ts +176 -41
  8. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +0 -8
  9. package/corpus/templates/analytics/actions/update-dashboard.ts +3 -1
  10. package/corpus/templates/analytics/app/components/SqlEditor.tsx +57 -0
  11. package/corpus/templates/analytics/app/components/SqlHighlight.tsx +27 -28
  12. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +130 -8
  13. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -3
  14. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewSqlPopover.tsx +4 -4
  15. package/corpus/templates/analytics/changelog/2026-06-24-active-user-dashboard-panels-classify-templates-more-accurat.md +6 -0
  16. package/corpus/templates/analytics/changelog/2026-06-24-dashboard-panel-deletes-now-stay-deleted-after-refresh.md +6 -0
  17. package/corpus/templates/analytics/changelog/2026-06-24-sql-panel-editors-now-highlight-query-syntax-and-keep-one-cl.md +6 -0
  18. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +2 -2
  19. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +9 -11
  20. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +6 -20
  21. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +45 -33
  22. package/corpus/templates/plan/changelog/2026-06-24-invalid-generated-recap-blocks-now-show-a-clear-warning-with.md +6 -0
  23. package/corpus/templates/plan/server/plan-content.ts +53 -3
  24. package/dist/agent/durable-background.d.ts +49 -0
  25. package/dist/agent/durable-background.d.ts.map +1 -1
  26. package/dist/agent/durable-background.js +51 -0
  27. package/dist/agent/durable-background.js.map +1 -1
  28. package/dist/agent/production-agent.d.ts.map +1 -1
  29. package/dist/agent/production-agent.js +15 -3
  30. package/dist/agent/production-agent.js.map +1 -1
  31. package/dist/cli/sync-builder-starter-manifest.d.ts.map +1 -1
  32. package/dist/cli/sync-builder-starter-manifest.js +21 -10
  33. package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
  34. package/dist/deploy/build.d.ts +61 -21
  35. package/dist/deploy/build.d.ts.map +1 -1
  36. package/dist/deploy/build.js +164 -41
  37. package/dist/deploy/build.js.map +1 -1
  38. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sync-builder-starter-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/sync-builder-starter-manifest.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAC/D,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,GAAG,MAAM,CAmBpE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG;IACjE,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAwBA;AAED,wBAAgB,oBAAoB,CAClC,kBAAkB,EAAE,WAAW,EAC/B,oBAAoB,EAAE,WAAW,GAChC,WAAW,CA4Bb;AAED,wBAAgB,wBAAwB,CACtC,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAChC,OAAO,CAKT;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAChC,IAAI,CAQN;AAMD,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,yBAAyB,CA6C5B;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAC5D,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CA0CA;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAmChE"}
1
+ {"version":3,"file":"sync-builder-starter-manifest.d.ts","sourceRoot":"","sources":["../../src/cli/sync-builder-starter-manifest.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAC/D,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C,wBAAgB,mBAAmB,CAAC,QAAQ,SAAgB,GAAG,MAAM,CAmBpE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG;IACjE,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAwBA;AAsBD,wBAAgB,oBAAoB,CAClC,kBAAkB,EAAE,WAAW,EAC/B,oBAAoB,EAAE,WAAW,GAChC,WAAW,CAgCb;AAED,wBAAgB,wBAAwB,CACtC,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAChC,OAAO,CAKT;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,kBAAkB,EAAE,MAAM,GAAG,IAAI,GAChC,IAAI,CAQN;AAMD,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE;IAChD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,yBAAyB,CA6C5B;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAC5D,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CA0CA;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAmChE"}
@@ -37,6 +37,21 @@ export function generateStandaloneChatManifest(repoRoot) {
37
37
  fs.rmSync(tempDir, { recursive: true, force: true });
38
38
  }
39
39
  }
40
+ function mergePackageJsonRecords(canonical, starter, starterPinnedKeys = []) {
41
+ const merged = { ...(canonical ?? {}) };
42
+ for (const [key, value] of Object.entries(starter ?? {})) {
43
+ if (!(key in merged)) {
44
+ merged[key] = value;
45
+ }
46
+ }
47
+ for (const key of starterPinnedKeys) {
48
+ const pinned = starter?.[key];
49
+ if (pinned) {
50
+ merged[key] = pinned;
51
+ }
52
+ }
53
+ return merged;
54
+ }
40
55
  export function mergeStarterManifest(starterPackageJson, canonicalPackageJson) {
41
56
  const merged = structuredClone(canonicalPackageJson);
42
57
  merged.name = starterPackageJson.name ?? STARTER_APP_NAME;
@@ -49,16 +64,12 @@ export function mergeStarterManifest(starterPackageJson, canonicalPackageJson) {
49
64
  if (starterPackageJson.private !== undefined) {
50
65
  merged.private = starterPackageJson.private;
51
66
  }
52
- const starterDeps = starterPackageJson.dependencies ??
53
- {};
54
- const canonicalDeps = canonicalPackageJson.dependencies ??
55
- {};
56
- merged.dependencies = {
57
- ...canonicalDeps,
58
- ...(starterDeps["@agent-native/core"]
59
- ? { "@agent-native/core": starterDeps["@agent-native/core"] }
60
- : {}),
61
- };
67
+ if (typeof starterPackageJson.packageManager === "string") {
68
+ merged.packageManager = starterPackageJson.packageManager;
69
+ }
70
+ merged.dependencies = mergePackageJsonRecords(canonicalPackageJson.dependencies, starterPackageJson.dependencies, ["@agent-native/core"]);
71
+ merged.devDependencies = mergePackageJsonRecords(canonicalPackageJson.devDependencies, starterPackageJson.devDependencies);
72
+ merged.scripts = mergePackageJsonRecords(canonicalPackageJson.scripts, starterPackageJson.scripts);
62
73
  return merged;
63
74
  }
64
75
  export function workspaceFileSyncChanged(existingWorkspace, canonicalWorkspace) {
@@ -1 +1 @@
1
- {"version":3,"file":"sync-builder-starter-manifest.js","sourceRoot":"","sources":["../../src/cli/sync-builder-starter-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { _postProcessStandalone } from \"./create.js\";\n\nexport const STARTER_APP_NAME = \"builder-agent-native-starter\";\nexport const CHAT_TEMPLATE = \"chat\";\n\ntype PackageJson = Record<string, unknown>;\n\nexport function findAgentNativeRoot(startDir = process.cwd()): string {\n let dir = path.resolve(startDir);\n for (let i = 0; i < 12; i++) {\n const chatPackageJson = path.join(\n dir,\n \"templates\",\n CHAT_TEMPLATE,\n \"package.json\",\n );\n if (fs.existsSync(chatPackageJson)) {\n return dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n throw new Error(\n \"Could not find agent-native repo root (expected templates/chat/package.json).\",\n );\n}\n\nexport function generateStandaloneChatManifest(repoRoot?: string): {\n packageJson: PackageJson;\n pnpmWorkspaceYaml: string | null;\n} {\n const root = repoRoot ?? findAgentNativeRoot();\n const chatTemplateDir = path.join(root, \"templates\", CHAT_TEMPLATE);\n const tempDir = fs.mkdtempSync(\n path.join(os.tmpdir(), \"an-builder-starter-sync-\"),\n );\n\n try {\n fs.cpSync(chatTemplateDir, tempDir, { recursive: true });\n _postProcessStandalone(STARTER_APP_NAME, tempDir, CHAT_TEMPLATE);\n\n const packageJson = JSON.parse(\n fs.readFileSync(path.join(tempDir, \"package.json\"), \"utf-8\"),\n ) as PackageJson;\n\n const workspacePath = path.join(tempDir, \"pnpm-workspace.yaml\");\n const pnpmWorkspaceYaml = fs.existsSync(workspacePath)\n ? fs.readFileSync(workspacePath, \"utf-8\")\n : null;\n\n return { packageJson, pnpmWorkspaceYaml };\n } finally {\n fs.rmSync(tempDir, { recursive: true, force: true });\n }\n}\n\nexport function mergeStarterManifest(\n starterPackageJson: PackageJson,\n canonicalPackageJson: PackageJson,\n): PackageJson {\n const merged = structuredClone(canonicalPackageJson) as PackageJson;\n\n merged.name = starterPackageJson.name ?? STARTER_APP_NAME;\n if (typeof starterPackageJson.displayName === \"string\") {\n merged.displayName = starterPackageJson.displayName;\n }\n if (typeof starterPackageJson.description === \"string\") {\n merged.description = starterPackageJson.description;\n }\n if (starterPackageJson.private !== undefined) {\n merged.private = starterPackageJson.private;\n }\n\n const starterDeps =\n (starterPackageJson.dependencies as Record<string, string> | undefined) ??\n {};\n const canonicalDeps =\n (canonicalPackageJson.dependencies as Record<string, string> | undefined) ??\n {};\n merged.dependencies = {\n ...canonicalDeps,\n ...(starterDeps[\"@agent-native/core\"]\n ? { \"@agent-native/core\": starterDeps[\"@agent-native/core\"] }\n : {}),\n };\n\n return merged;\n}\n\nexport function workspaceFileSyncChanged(\n existingWorkspace: string | null,\n canonicalWorkspace: string | null,\n): boolean {\n if (canonicalWorkspace === null) {\n return existingWorkspace !== null;\n }\n return existingWorkspace !== canonicalWorkspace;\n}\n\nexport function applyWorkspaceFileSync(\n targetPath: string,\n canonicalWorkspace: string | null,\n): void {\n if (canonicalWorkspace === null) {\n if (fs.existsSync(targetPath)) {\n fs.unlinkSync(targetPath);\n }\n return;\n }\n fs.writeFileSync(targetPath, canonicalWorkspace);\n}\n\nfunction stableJson(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport type SyncStarterManifestResult = {\n changed: boolean;\n packageJson: PackageJson;\n pnpmWorkspaceYaml: string | null;\n};\n\nexport function syncStarterManifestFiles(options: {\n starterPackageJsonPath: string;\n starterPnpmWorkspacePath?: string;\n repoRoot?: string;\n write?: boolean;\n}): SyncStarterManifestResult {\n const { packageJson: canonical, pnpmWorkspaceYaml } =\n generateStandaloneChatManifest(options.repoRoot);\n\n const starterPackageJson = JSON.parse(\n fs.readFileSync(options.starterPackageJsonPath, \"utf-8\"),\n ) as PackageJson;\n const mergedPackageJson = mergeStarterManifest(starterPackageJson, canonical);\n\n let workspaceChanged = false;\n const existingWorkspace =\n options.starterPnpmWorkspacePath &&\n fs.existsSync(options.starterPnpmWorkspacePath)\n ? fs.readFileSync(options.starterPnpmWorkspacePath, \"utf-8\")\n : null;\n\n workspaceChanged = workspaceFileSyncChanged(\n existingWorkspace,\n pnpmWorkspaceYaml,\n );\n\n const packageChanged =\n stableJson(starterPackageJson) !== stableJson(mergedPackageJson);\n const changed = packageChanged || workspaceChanged;\n\n if (options.write && changed) {\n if (packageChanged) {\n fs.writeFileSync(\n options.starterPackageJsonPath,\n stableJson(mergedPackageJson),\n );\n }\n if (workspaceChanged && options.starterPnpmWorkspacePath) {\n applyWorkspaceFileSync(\n options.starterPnpmWorkspacePath,\n pnpmWorkspaceYaml,\n );\n }\n }\n\n return {\n changed,\n packageJson: mergedPackageJson,\n pnpmWorkspaceYaml,\n };\n}\n\nexport function parseSyncStarterManifestArgs(argv: string[]): {\n command: \"merge\" | \"generate\";\n starterPackageJsonPath?: string;\n starterPnpmWorkspacePath?: string;\n write: boolean;\n repoRoot?: string;\n} {\n const [commandRaw, ...rest] = argv;\n const command = commandRaw === \"generate\" ? \"generate\" : \"merge\";\n let starterPackageJsonPath: string | undefined;\n let starterPnpmWorkspacePath: string | undefined;\n let write = false;\n let repoRoot: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n if (arg === \"--write\") {\n write = true;\n continue;\n }\n if (arg === \"--starter-package-json\") {\n starterPackageJsonPath = rest[++i];\n continue;\n }\n if (arg === \"--starter-pnpm-workspace\") {\n starterPnpmWorkspacePath = rest[++i];\n continue;\n }\n if (arg === \"--repo-root\") {\n repoRoot = rest[++i];\n continue;\n }\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n if (command === \"merge\" && !starterPackageJsonPath) {\n throw new Error(\n \"merge requires --starter-package-json <path> [--starter-pnpm-workspace <path>] [--write] [--repo-root <path>]\",\n );\n }\n\n return {\n command,\n starterPackageJsonPath,\n starterPnpmWorkspacePath,\n write,\n repoRoot,\n };\n}\n\nexport function runSyncStarterManifestCli(argv: string[]): number {\n const args = parseSyncStarterManifestArgs(argv);\n\n if (args.command === \"generate\") {\n const { packageJson, pnpmWorkspaceYaml } = generateStandaloneChatManifest(\n args.repoRoot,\n );\n process.stdout.write(stableJson(packageJson));\n if (pnpmWorkspaceYaml) {\n process.stdout.write(\"\\n--- pnpm-workspace.yaml ---\\n\");\n process.stdout.write(pnpmWorkspaceYaml);\n }\n return 0;\n }\n\n const result = syncStarterManifestFiles({\n starterPackageJsonPath: args.starterPackageJsonPath!,\n starterPnpmWorkspacePath: args.starterPnpmWorkspacePath,\n repoRoot: args.repoRoot,\n write: args.write,\n });\n\n if (result.changed) {\n console.log(\n args.write\n ? \"Updated builder-agent-native-starter manifest from templates/chat.\"\n : \"builder-agent-native-starter manifest is out of date with templates/chat.\",\n );\n return args.write ? 0 : 1;\n }\n\n console.log(\n \"builder-agent-native-starter manifest already matches templates/chat.\",\n );\n return 0;\n}\n\nconst isDirectRun =\n process.argv[1] &&\n path.resolve(process.argv[1]) ===\n path.resolve(fileURLToPath(import.meta.url));\n\nif (isDirectRun) {\n const exitCode = runSyncStarterManifestCli(process.argv.slice(2));\n process.exit(exitCode);\n}\n"]}
1
+ {"version":3,"file":"sync-builder-starter-manifest.js","sourceRoot":"","sources":["../../src/cli/sync-builder-starter-manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { _postProcessStandalone } from \"./create.js\";\n\nexport const STARTER_APP_NAME = \"builder-agent-native-starter\";\nexport const CHAT_TEMPLATE = \"chat\";\n\ntype PackageJson = Record<string, unknown>;\n\nexport function findAgentNativeRoot(startDir = process.cwd()): string {\n let dir = path.resolve(startDir);\n for (let i = 0; i < 12; i++) {\n const chatPackageJson = path.join(\n dir,\n \"templates\",\n CHAT_TEMPLATE,\n \"package.json\",\n );\n if (fs.existsSync(chatPackageJson)) {\n return dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n throw new Error(\n \"Could not find agent-native repo root (expected templates/chat/package.json).\",\n );\n}\n\nexport function generateStandaloneChatManifest(repoRoot?: string): {\n packageJson: PackageJson;\n pnpmWorkspaceYaml: string | null;\n} {\n const root = repoRoot ?? findAgentNativeRoot();\n const chatTemplateDir = path.join(root, \"templates\", CHAT_TEMPLATE);\n const tempDir = fs.mkdtempSync(\n path.join(os.tmpdir(), \"an-builder-starter-sync-\"),\n );\n\n try {\n fs.cpSync(chatTemplateDir, tempDir, { recursive: true });\n _postProcessStandalone(STARTER_APP_NAME, tempDir, CHAT_TEMPLATE);\n\n const packageJson = JSON.parse(\n fs.readFileSync(path.join(tempDir, \"package.json\"), \"utf-8\"),\n ) as PackageJson;\n\n const workspacePath = path.join(tempDir, \"pnpm-workspace.yaml\");\n const pnpmWorkspaceYaml = fs.existsSync(workspacePath)\n ? fs.readFileSync(workspacePath, \"utf-8\")\n : null;\n\n return { packageJson, pnpmWorkspaceYaml };\n } finally {\n fs.rmSync(tempDir, { recursive: true, force: true });\n }\n}\n\nfunction mergePackageJsonRecords(\n canonical: Record<string, string> | undefined,\n starter: Record<string, string> | undefined,\n starterPinnedKeys: string[] = [],\n): Record<string, string> {\n const merged = { ...(canonical ?? {}) };\n for (const [key, value] of Object.entries(starter ?? {})) {\n if (!(key in merged)) {\n merged[key] = value;\n }\n }\n for (const key of starterPinnedKeys) {\n const pinned = starter?.[key];\n if (pinned) {\n merged[key] = pinned;\n }\n }\n return merged;\n}\n\nexport function mergeStarterManifest(\n starterPackageJson: PackageJson,\n canonicalPackageJson: PackageJson,\n): PackageJson {\n const merged = structuredClone(canonicalPackageJson) as PackageJson;\n\n merged.name = starterPackageJson.name ?? STARTER_APP_NAME;\n if (typeof starterPackageJson.displayName === \"string\") {\n merged.displayName = starterPackageJson.displayName;\n }\n if (typeof starterPackageJson.description === \"string\") {\n merged.description = starterPackageJson.description;\n }\n if (starterPackageJson.private !== undefined) {\n merged.private = starterPackageJson.private;\n }\n if (typeof starterPackageJson.packageManager === \"string\") {\n merged.packageManager = starterPackageJson.packageManager;\n }\n\n merged.dependencies = mergePackageJsonRecords(\n canonicalPackageJson.dependencies as Record<string, string> | undefined,\n starterPackageJson.dependencies as Record<string, string> | undefined,\n [\"@agent-native/core\"],\n );\n merged.devDependencies = mergePackageJsonRecords(\n canonicalPackageJson.devDependencies as Record<string, string> | undefined,\n starterPackageJson.devDependencies as Record<string, string> | undefined,\n );\n merged.scripts = mergePackageJsonRecords(\n canonicalPackageJson.scripts as Record<string, string> | undefined,\n starterPackageJson.scripts as Record<string, string> | undefined,\n );\n\n return merged;\n}\n\nexport function workspaceFileSyncChanged(\n existingWorkspace: string | null,\n canonicalWorkspace: string | null,\n): boolean {\n if (canonicalWorkspace === null) {\n return existingWorkspace !== null;\n }\n return existingWorkspace !== canonicalWorkspace;\n}\n\nexport function applyWorkspaceFileSync(\n targetPath: string,\n canonicalWorkspace: string | null,\n): void {\n if (canonicalWorkspace === null) {\n if (fs.existsSync(targetPath)) {\n fs.unlinkSync(targetPath);\n }\n return;\n }\n fs.writeFileSync(targetPath, canonicalWorkspace);\n}\n\nfunction stableJson(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport type SyncStarterManifestResult = {\n changed: boolean;\n packageJson: PackageJson;\n pnpmWorkspaceYaml: string | null;\n};\n\nexport function syncStarterManifestFiles(options: {\n starterPackageJsonPath: string;\n starterPnpmWorkspacePath?: string;\n repoRoot?: string;\n write?: boolean;\n}): SyncStarterManifestResult {\n const { packageJson: canonical, pnpmWorkspaceYaml } =\n generateStandaloneChatManifest(options.repoRoot);\n\n const starterPackageJson = JSON.parse(\n fs.readFileSync(options.starterPackageJsonPath, \"utf-8\"),\n ) as PackageJson;\n const mergedPackageJson = mergeStarterManifest(starterPackageJson, canonical);\n\n let workspaceChanged = false;\n const existingWorkspace =\n options.starterPnpmWorkspacePath &&\n fs.existsSync(options.starterPnpmWorkspacePath)\n ? fs.readFileSync(options.starterPnpmWorkspacePath, \"utf-8\")\n : null;\n\n workspaceChanged = workspaceFileSyncChanged(\n existingWorkspace,\n pnpmWorkspaceYaml,\n );\n\n const packageChanged =\n stableJson(starterPackageJson) !== stableJson(mergedPackageJson);\n const changed = packageChanged || workspaceChanged;\n\n if (options.write && changed) {\n if (packageChanged) {\n fs.writeFileSync(\n options.starterPackageJsonPath,\n stableJson(mergedPackageJson),\n );\n }\n if (workspaceChanged && options.starterPnpmWorkspacePath) {\n applyWorkspaceFileSync(\n options.starterPnpmWorkspacePath,\n pnpmWorkspaceYaml,\n );\n }\n }\n\n return {\n changed,\n packageJson: mergedPackageJson,\n pnpmWorkspaceYaml,\n };\n}\n\nexport function parseSyncStarterManifestArgs(argv: string[]): {\n command: \"merge\" | \"generate\";\n starterPackageJsonPath?: string;\n starterPnpmWorkspacePath?: string;\n write: boolean;\n repoRoot?: string;\n} {\n const [commandRaw, ...rest] = argv;\n const command = commandRaw === \"generate\" ? \"generate\" : \"merge\";\n let starterPackageJsonPath: string | undefined;\n let starterPnpmWorkspacePath: string | undefined;\n let write = false;\n let repoRoot: string | undefined;\n\n for (let i = 0; i < rest.length; i++) {\n const arg = rest[i];\n if (arg === \"--write\") {\n write = true;\n continue;\n }\n if (arg === \"--starter-package-json\") {\n starterPackageJsonPath = rest[++i];\n continue;\n }\n if (arg === \"--starter-pnpm-workspace\") {\n starterPnpmWorkspacePath = rest[++i];\n continue;\n }\n if (arg === \"--repo-root\") {\n repoRoot = rest[++i];\n continue;\n }\n throw new Error(`Unknown argument: ${arg}`);\n }\n\n if (command === \"merge\" && !starterPackageJsonPath) {\n throw new Error(\n \"merge requires --starter-package-json <path> [--starter-pnpm-workspace <path>] [--write] [--repo-root <path>]\",\n );\n }\n\n return {\n command,\n starterPackageJsonPath,\n starterPnpmWorkspacePath,\n write,\n repoRoot,\n };\n}\n\nexport function runSyncStarterManifestCli(argv: string[]): number {\n const args = parseSyncStarterManifestArgs(argv);\n\n if (args.command === \"generate\") {\n const { packageJson, pnpmWorkspaceYaml } = generateStandaloneChatManifest(\n args.repoRoot,\n );\n process.stdout.write(stableJson(packageJson));\n if (pnpmWorkspaceYaml) {\n process.stdout.write(\"\\n--- pnpm-workspace.yaml ---\\n\");\n process.stdout.write(pnpmWorkspaceYaml);\n }\n return 0;\n }\n\n const result = syncStarterManifestFiles({\n starterPackageJsonPath: args.starterPackageJsonPath!,\n starterPnpmWorkspacePath: args.starterPnpmWorkspacePath,\n repoRoot: args.repoRoot,\n write: args.write,\n });\n\n if (result.changed) {\n console.log(\n args.write\n ? \"Updated builder-agent-native-starter manifest from templates/chat.\"\n : \"builder-agent-native-starter manifest is out of date with templates/chat.\",\n );\n return args.write ? 0 : 1;\n }\n\n console.log(\n \"builder-agent-native-starter manifest already matches templates/chat.\",\n );\n return 0;\n}\n\nconst isDirectRun =\n process.argv[1] &&\n path.resolve(process.argv[1]) ===\n path.resolve(fileURLToPath(import.meta.url));\n\nif (isDirectRun) {\n const exitCode = runSyncStarterManifestCli(process.argv.slice(2));\n process.exit(exitCode);\n}\n"]}
@@ -58,30 +58,70 @@ export declare function findInstalledResvgPackages(nodeModulesRoots: string[]):
58
58
  */
59
59
  export declare function isDurableBackgroundDeployEnabled(): boolean;
60
60
  /**
61
- * Single-template Netlify build: emit a SECOND function whose name ends in
62
- * `-background`, re-exporting the same `main.mjs` handler bundle, so the chat
63
- * `_process-run` POST lands on Netlify's async (15-min) function instead of the
64
- * synchronous one. Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
61
+ * Single-template Netlify build: emit an async (background) function INSIDE the
62
+ * scanned functions dir so the chat `_process-run` worker runs on Netlify's
63
+ * 15-min async function instead of the synchronous `/*` catch-all.
64
+ * Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
65
65
  *
66
- * Nitro's `netlify` preset emits a single function at
67
- * `.netlify/functions-internal/server` (`server.mjs` `main.mjs`). We copy
68
- * that directory to a sibling `<...>-background` function and write an entry
69
- * with a `config.path` of the process-run route.
66
+ * GROUNDED IN THE REAL NETLIFY BUILD OUTPUT (verified from a local Nitro build):
67
+ * - Nitro's `netlify` preset emits exactly ONE function source at
68
+ * `.netlify/functions-internal/server/`. `server.mjs` re-exports `main.mjs`
69
+ * and declares `export const config = { path: "/*", excludedPath:
70
+ * ["/.netlify/*"], preferStatic: true, ... }`. Nitro writes NO `netlify.toml`
71
+ * and NO `[[redirects]]`; the `/*` catch-all is an IN-CODE Functions-API-v2
72
+ * `config.path`.
73
+ * - The generated `.netlify/netlify.toml` sets
74
+ * `functionsDirectory = ".netlify/functions-internal"`. Netlify scans EXACTLY
75
+ * that dir; functions placed anywhere else (e.g. `.netlify/functions/`, which
76
+ * is the BUILD OUTPUT dir where `@netlify/build` later writes the zipped
77
+ * functions + `manifest.json`) are NEVER deployed.
78
+ * - On Netlify CI, `@netlify/build` reads each scanned function's
79
+ * `export const config`, zips it, and materializes
80
+ * `.netlify/functions/manifest.json` with `routes` derived from each
81
+ * `config.path`. So per-file `export const config` (including `background` and
82
+ * `path`) IS honored — the `server` manifest entry's `routes: [{ pattern:
83
+ * "/*" }]` came straight from `server.mjs`'s `config.path`.
70
84
  *
71
- * The function declares `background: true` so Netlify invokes it ASYNC (HTTP
72
- * 202 ack) with the 15-min budget, and a `config.path` of the process-run route
73
- * so the `_process-run` self-dispatch lands on it. The earlier version set the
74
- * path but omitted `background: true` and relied on the legacy `-background`
75
- * filename which the `config` object overrides so Netlify served it
76
- * SYNCHRONOUSLY (~60s) and the durable worker never got the 15-min budget
77
- * (confirmed live: a POST to the process-run path returned a synchronous 401
78
- * from the handler instead of a 202 async ack).
85
+ * THEREFORE we:
86
+ * 1. Emit the background function INTO the scanned dir
87
+ * (`.netlify/functions-internal/server-agent-background/`), sharing the same
88
+ * built `main.mjs` bundle, so Netlify discovers it and honors its config.
89
+ * 2. Give its `export const config` BOTH `background: true` (→ async invoke,
90
+ * immediate 202, 15-min budget) AND `path: AGENT_CHAT_PROCESS_RUN_PATH` (so
91
+ * it claims that exact path at function-matching time, which Netlify
92
+ * evaluates BEFORE redirects step 10 vs 11 in the request chain).
93
+ * 3. PATCH the Nitro `server` function's own `server.mjs` so its catch-all
94
+ * `config.path: "/*"` EXCLUDES `AGENT_CHAT_PROCESS_RUN_PATH` (append it to
95
+ * `excludedPath`). Netlify does NOT define a winner when two serverless
96
+ * functions both match a path; rather than rely on that undocumented order,
97
+ * we make the match UNAMBIGUOUS — only the background function matches
98
+ * `_process-run`, and `server` matches everything else exactly as before.
99
+ * 4. Set `globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true` at cold start
100
+ * (read back by `isInBackgroundFunctionRuntime()` so the worker takes the
101
+ * ~13-min soft-timeout). A `globalThis` flag — NOT `process.env` — keeps the
102
+ * no-env-mutation guard satisfied and carries no cross-request state.
79
103
  *
80
- * ⚠️ One Netlify runtime behavior still resolves only on a real deploy: the
81
- * routing precedence between this function's `config.path` and Nitro's catch-all
82
- * for that exact path. If the catch-all wins, the run still completes via the
83
- * 40s soft-timeout path on the sync function (no durable win, no regression).
84
- * See docs/design/durable-agent-runs.md (Open risks #1).
104
+ * With a real `config.path` the function is reachable at that path directly, so
105
+ * the foreground POSTs to `AGENT_CHAT_PROCESS_RUN_PATH`
106
+ * (`resolveAgentChatProcessRunDispatchPath`) and the request entry no longer
107
+ * needs to rewrite the path it already arrives at the framework route. We keep
108
+ * a defensive normalize-to-PROCESS_RUN_PATH in the entry anyway (cheap, and it
109
+ * makes the function correct even if reached via its default function url).
110
+ *
111
+ * WHY THIS BEATS ALL THREE PRIOR FAILURES:
112
+ * - Attempts 1 & 2 emitted into `functions-internal` (correct dir) with a
113
+ * `config.path` but did NOT exclude that path from the `server` `/*`
114
+ * catch-all. Two functions matched `_process-run`; the order is undocumented
115
+ * and the catch-all `server` (priority 0, synchronous) won → SYNC 401, not a
116
+ * 202. We now exclude the path from `server`, so only the async function
117
+ * matches.
118
+ * - Attempt 3 emitted a standalone function into `.netlify/functions/` — the
119
+ * OUTPUT dir, which Netlify does not scan — so it never entered the manifest
120
+ * → 404. We now emit into the SCANNED `functions-internal` dir.
121
+ *
122
+ * Safety net regardless of Netlify routing nuance: if the dispatch fast-fails
123
+ * (e.g. the function was not emitted), the foreground handler degrades to an
124
+ * inline 40s synchronous run (see production-agent.ts).
85
125
  */
86
126
  export declare function emitSingleTemplateNetlifyBackgroundFunction(projectCwd: string): void;
87
127
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AA4B7B,eAAO,MAAM,6BAA6B,UAiBzC,CAAC;AAuBF,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,MAAM,EAAE,GACpB,MAAM,CAaR;AAgBD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAgBvE,wBAAgB,yCAAyC,CACvD,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAK,GACf,IAAI,CAQN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,EAAE,EACrB,kBAAkB,GAAE,MAAM,EAAO,EACjC,OAAO,GAAE,gBAAgB,EAAO,EAChC,aAAa,GAAE,oBAAoB,GAAG,IAAW,EACjD,mBAAmB,GAAE,MAAM,EAAO,EAClC,gBAAgB,SAAmC,GAClD,MAAM,CAskBR;AAyXD,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAkHD,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,iBAAiB,cAAoB,QAoCtC;AAuBD,KAAK,0BAA0B,GAAG,OAAO,GAAG,KAAK,CAAC;AAQlD,wBAAgB,qCAAqC,CACnD,YAAY,GAAE,MAAM,CAAC,QAA2B,EAChD,QAAQ,GAAE,MAAM,CAAC,YAA2B,EAC5C,UAAU,GAAE,0BAA0B,GAAG,IAAgD,GACxF,OAAO,CAOT;AAqED,wBAAgB,gCAAgC,CAC9C,gBAAgB,EAAE,MAAM,EAAE,GACzB,MAAM,GAAG,IAAI,CA8Bf;AAED,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,EAAE,GACzB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gCAAgC,IAAI,OAAO,CAK1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,2CAA2C,CACzD,UAAU,EAAE,MAAM,GACjB,IAAI,CA2DN;AAkND;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/deploy/build.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AA+B7B,eAAO,MAAM,6BAA6B,UAiBzC,CAAC;AAuBF,wBAAgB,wCAAwC,CACtD,WAAW,EAAE,MAAM,EAAE,GACpB,MAAM,CAaR;AAgBD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAgBvE,wBAAgB,yCAAyC,CACvD,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,WAAW,SAAK,GACf,IAAI,CAQN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,eAAe,EAAE,EACzB,WAAW,EAAE,MAAM,EAAE,EACrB,kBAAkB,GAAE,MAAM,EAAO,EACjC,OAAO,GAAE,gBAAgB,EAAO,EAChC,aAAa,GAAE,oBAAoB,GAAG,IAAW,EACjD,mBAAmB,GAAE,MAAM,EAAO,EAClC,gBAAgB,SAAmC,GAClD,MAAM,CAskBR;AAyXD,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAkHD,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,iBAAiB,cAAoB,QAoCtC;AAuBD,KAAK,0BAA0B,GAAG,OAAO,GAAG,KAAK,CAAC;AAQlD,wBAAgB,qCAAqC,CACnD,YAAY,GAAE,MAAM,CAAC,QAA2B,EAChD,QAAQ,GAAE,MAAM,CAAC,YAA2B,EAC5C,UAAU,GAAE,0BAA0B,GAAG,IAAgD,GACxF,OAAO,CAOT;AAqED,wBAAgB,gCAAgC,CAC9C,gBAAgB,EAAE,MAAM,EAAE,GACzB,MAAM,GAAG,IAAI,CA8Bf;AAED,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,EAAE,GACzB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gCAAgC,IAAI,OAAO,CAK1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,wBAAgB,2CAA2C,CACzD,UAAU,EAAE,MAAM,GACjB,IAAI,CA8FN;AA2QD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
@@ -21,7 +21,7 @@ import { discoverApiRoutes, discoverPlugins, discoverActionFiles, getMissingDefa
21
21
  import { getWorkspaceCoreExports, } from "./workspace-core.js";
22
22
  import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
23
23
  import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
24
- import { AGENT_CHAT_PROCESS_RUN_PATH } from "../agent/durable-background.js";
24
+ import { AGENT_BACKGROUND_FUNCTION_NAME, AGENT_CHAT_PROCESS_RUN_PATH, } from "../agent/durable-background.js";
25
25
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, } from "../shared/social-meta.js";
26
26
  import { DEFAULT_SSR_CDN_CACHE_CONTROL, DEFAULT_SSR_NETLIFY_CDN_CACHE_CONTROL, DEFAULT_SPECULATION_RULES_PATH, DEFAULT_SSR_CACHE_CONTROL, } from "../shared/cache-control.js";
27
27
  import { collectImmutableAssetPaths, IMMUTABLE_ASSET_CACHE_CONTROL, IMMUTABLE_ASSET_CACHE_HEADERS, prefixAssetPath, } from "./immutable-assets.js";
@@ -1252,34 +1252,74 @@ export function isDurableBackgroundDeployEnabled() {
1252
1252
  return !(v === "0" || v === "false" || v === "no" || v === "off");
1253
1253
  }
1254
1254
  /**
1255
- * Single-template Netlify build: emit a SECOND function whose name ends in
1256
- * `-background`, re-exporting the same `main.mjs` handler bundle, so the chat
1257
- * `_process-run` POST lands on Netlify's async (15-min) function instead of the
1258
- * synchronous one. Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
1255
+ * Single-template Netlify build: emit an async (background) function INSIDE the
1256
+ * scanned functions dir so the chat `_process-run` worker runs on Netlify's
1257
+ * 15-min async function instead of the synchronous `/*` catch-all.
1258
+ * Additive + flag-gated (see `isDurableBackgroundDeployEnabled`).
1259
1259
  *
1260
- * Nitro's `netlify` preset emits a single function at
1261
- * `.netlify/functions-internal/server` (`server.mjs` `main.mjs`). We copy
1262
- * that directory to a sibling `<...>-background` function and write an entry
1263
- * with a `config.path` of the process-run route.
1260
+ * GROUNDED IN THE REAL NETLIFY BUILD OUTPUT (verified from a local Nitro build):
1261
+ * - Nitro's `netlify` preset emits exactly ONE function source at
1262
+ * `.netlify/functions-internal/server/`. `server.mjs` re-exports `main.mjs`
1263
+ * and declares `export const config = { path: "/*", excludedPath:
1264
+ * ["/.netlify/*"], preferStatic: true, ... }`. Nitro writes NO `netlify.toml`
1265
+ * and NO `[[redirects]]`; the `/*` catch-all is an IN-CODE Functions-API-v2
1266
+ * `config.path`.
1267
+ * - The generated `.netlify/netlify.toml` sets
1268
+ * `functionsDirectory = ".netlify/functions-internal"`. Netlify scans EXACTLY
1269
+ * that dir; functions placed anywhere else (e.g. `.netlify/functions/`, which
1270
+ * is the BUILD OUTPUT dir where `@netlify/build` later writes the zipped
1271
+ * functions + `manifest.json`) are NEVER deployed.
1272
+ * - On Netlify CI, `@netlify/build` reads each scanned function's
1273
+ * `export const config`, zips it, and materializes
1274
+ * `.netlify/functions/manifest.json` with `routes` derived from each
1275
+ * `config.path`. So per-file `export const config` (including `background` and
1276
+ * `path`) IS honored — the `server` manifest entry's `routes: [{ pattern:
1277
+ * "/*" }]` came straight from `server.mjs`'s `config.path`.
1264
1278
  *
1265
- * The function declares `background: true` so Netlify invokes it ASYNC (HTTP
1266
- * 202 ack) with the 15-min budget, and a `config.path` of the process-run route
1267
- * so the `_process-run` self-dispatch lands on it. The earlier version set the
1268
- * path but omitted `background: true` and relied on the legacy `-background`
1269
- * filename which the `config` object overrides so Netlify served it
1270
- * SYNCHRONOUSLY (~60s) and the durable worker never got the 15-min budget
1271
- * (confirmed live: a POST to the process-run path returned a synchronous 401
1272
- * from the handler instead of a 202 async ack).
1279
+ * THEREFORE we:
1280
+ * 1. Emit the background function INTO the scanned dir
1281
+ * (`.netlify/functions-internal/server-agent-background/`), sharing the same
1282
+ * built `main.mjs` bundle, so Netlify discovers it and honors its config.
1283
+ * 2. Give its `export const config` BOTH `background: true` (→ async invoke,
1284
+ * immediate 202, 15-min budget) AND `path: AGENT_CHAT_PROCESS_RUN_PATH` (so
1285
+ * it claims that exact path at function-matching time, which Netlify
1286
+ * evaluates BEFORE redirects step 10 vs 11 in the request chain).
1287
+ * 3. PATCH the Nitro `server` function's own `server.mjs` so its catch-all
1288
+ * `config.path: "/*"` EXCLUDES `AGENT_CHAT_PROCESS_RUN_PATH` (append it to
1289
+ * `excludedPath`). Netlify does NOT define a winner when two serverless
1290
+ * functions both match a path; rather than rely on that undocumented order,
1291
+ * we make the match UNAMBIGUOUS — only the background function matches
1292
+ * `_process-run`, and `server` matches everything else exactly as before.
1293
+ * 4. Set `globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true` at cold start
1294
+ * (read back by `isInBackgroundFunctionRuntime()` so the worker takes the
1295
+ * ~13-min soft-timeout). A `globalThis` flag — NOT `process.env` — keeps the
1296
+ * no-env-mutation guard satisfied and carries no cross-request state.
1273
1297
  *
1274
- * ⚠️ One Netlify runtime behavior still resolves only on a real deploy: the
1275
- * routing precedence between this function's `config.path` and Nitro's catch-all
1276
- * for that exact path. If the catch-all wins, the run still completes via the
1277
- * 40s soft-timeout path on the sync function (no durable win, no regression).
1278
- * See docs/design/durable-agent-runs.md (Open risks #1).
1298
+ * With a real `config.path` the function is reachable at that path directly, so
1299
+ * the foreground POSTs to `AGENT_CHAT_PROCESS_RUN_PATH`
1300
+ * (`resolveAgentChatProcessRunDispatchPath`) and the request entry no longer
1301
+ * needs to rewrite the path it already arrives at the framework route. We keep
1302
+ * a defensive normalize-to-PROCESS_RUN_PATH in the entry anyway (cheap, and it
1303
+ * makes the function correct even if reached via its default function url).
1304
+ *
1305
+ * WHY THIS BEATS ALL THREE PRIOR FAILURES:
1306
+ * - Attempts 1 & 2 emitted into `functions-internal` (correct dir) with a
1307
+ * `config.path` but did NOT exclude that path from the `server` `/*`
1308
+ * catch-all. Two functions matched `_process-run`; the order is undocumented
1309
+ * and the catch-all `server` (priority 0, synchronous) won → SYNC 401, not a
1310
+ * 202. We now exclude the path from `server`, so only the async function
1311
+ * matches.
1312
+ * - Attempt 3 emitted a standalone function into `.netlify/functions/` — the
1313
+ * OUTPUT dir, which Netlify does not scan — so it never entered the manifest
1314
+ * → 404. We now emit into the SCANNED `functions-internal` dir.
1315
+ *
1316
+ * Safety net regardless of Netlify routing nuance: if the dispatch fast-fails
1317
+ * (e.g. the function was not emitted), the foreground handler degrades to an
1318
+ * inline 40s synchronous run (see production-agent.ts).
1279
1319
  */
1280
1320
  export function emitSingleTemplateNetlifyBackgroundFunction(projectCwd) {
1281
- const functionsDir = path.join(projectCwd, ".netlify", "functions-internal");
1282
- const serverDir = path.join(functionsDir, "server");
1321
+ const internalDir = path.join(projectCwd, ".netlify", "functions-internal");
1322
+ const serverDir = path.join(internalDir, "server");
1283
1323
  if (!fs.existsSync(path.join(serverDir, "main.mjs"))) {
1284
1324
  // Nitro output layout differs from what we expected — skip rather than
1285
1325
  // guess. The single-function deploy is unaffected.
@@ -1287,12 +1327,22 @@ export function emitSingleTemplateNetlifyBackgroundFunction(projectCwd) {
1287
1327
  "at .netlify/functions-internal/server/main.mjs was not found.");
1288
1328
  return;
1289
1329
  }
1290
- const backgroundName = "server-agent-background";
1291
- const dest = path.join(functionsDir, backgroundName);
1330
+ const backgroundName = AGENT_BACKGROUND_FUNCTION_NAME;
1331
+ // Emit INTO the SCANNED functions dir (functions-internal) so Netlify discovers
1332
+ // the function and honors its `export const config`. `.netlify/functions/` is
1333
+ // the build OUTPUT dir (where @netlify/build writes the zip + manifest) and is
1334
+ // NOT scanned — emitting there is why the standalone attempt 404'd.
1335
+ const dest = path.join(internalDir, backgroundName);
1292
1336
  fs.rmSync(dest, { recursive: true, force: true });
1293
1337
  copyDir(serverDir, dest);
1294
- // Drop the original Nitro entry so our background entry is the entrypoint.
1338
+ // Drop the original Nitro `/*` entry so our entry is the entrypoint and the
1339
+ // copied bundle does NOT re-register the catch-all `config.path`.
1295
1340
  fs.rmSync(path.join(dest, "server.mjs"), { force: true });
1341
+ // Make the `server` `/*` catch-all NOT match the process-run path, so only the
1342
+ // async background function matches it (function-vs-function path order is
1343
+ // undocumented on Netlify — don't rely on it).
1344
+ excludeProcessRunPathFromServerCatchAll(serverDir);
1345
+ const processRunPath = JSON.stringify(AGENT_CHAT_PROCESS_RUN_PATH);
1296
1346
  const entry = `// Mark this isolate as the durable background runtime BEFORE the handler
1297
1347
  // bundle is imported, so isInBackgroundFunctionRuntime() reliably returns true
1298
1348
  // in this function. The deployed Lambda name is NOT guaranteed to end in
@@ -1302,35 +1352,108 @@ export function emitSingleTemplateNetlifyBackgroundFunction(projectCwd) {
1302
1352
  // set-once isolate marker read back by isInBackgroundFunctionRuntime().
1303
1353
  globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true;
1304
1354
 
1355
+ // The framework route the Nitro router dispatches to (the _process-run plugin).
1356
+ const PROCESS_RUN_PATH = ${processRunPath};
1357
+
1305
1358
  let cachedHandler;
1306
1359
 
1307
- export default async function handler(...args) {
1360
+ // Netlify v2 invokes this as (request, context). The Nitro netlify handler is a
1361
+ // Web-standard \`async (Request) => Response\` (see nitro/presets/netlify/runtime).
1362
+ // Because this function declares \`config.path = PROCESS_RUN_PATH\`, Netlify routes
1363
+ // that exact path here and the request already arrives as PROCESS_RUN_PATH — no
1364
+ // rewrite is needed. We still NORMALIZE the pathname to PROCESS_RUN_PATH so the
1365
+ // function stays correct even if it is ever reached via its default function url
1366
+ // (/.netlify/functions/${backgroundName}). Method, ALL headers (the HMAC
1367
+ // Authorization: Bearer MUST survive — the plugin verifies it) and the body are
1368
+ // preserved by cloning the incoming Request with only its URL pathname set.
1369
+ export default async function handler(request) {
1308
1370
  cachedHandler ??= (await import("./main.mjs")).default;
1309
- return cachedHandler(...args);
1371
+ const url = new URL(request.url);
1372
+ url.pathname = PROCESS_RUN_PATH;
1373
+ // Read the body once and pass it through. GET/HEAD have no body.
1374
+ const method = request.method || "POST";
1375
+ const hasBody = method !== "GET" && method !== "HEAD";
1376
+ const body = hasBody ? await request.text() : undefined;
1377
+ const rewritten = new Request(url.toString(), {
1378
+ method,
1379
+ headers: request.headers,
1380
+ body,
1381
+ });
1382
+ return cachedHandler(rewritten);
1310
1383
  }
1311
1384
 
1312
1385
  export const config = {
1313
1386
  name: "agent background handler",
1314
1387
  generator: "agent-native build",
1315
- // background: true is what actually makes Netlify invoke this ASYNCHRONOUSLY
1316
- // (immediate HTTP 202 ack) with the 15-minute budget. Without it, a function
1317
- // that declares a custom \`path\` is served SYNCHRONOUSLY (~60s) even when its
1318
- // file name ends in "-background" the \`config\` object overrides the legacy
1319
- // filename convention. That omission is why the durable worker was capped at
1320
- // ~60s in prod (verified live: POST to the process-run path returned a
1321
- // synchronous 401 from the handler, not a 202 async ack). See Netlify docs:
1322
- // build/functions/background-functions + build/functions/configuration.
1388
+ // background: true makes Netlify invoke this ASYNCHRONOUSLY (immediate HTTP
1389
+ // 202 ack) with the 15-minute budget (Netlify docs:
1390
+ // build/functions/background-functions + build/functions/api). path claims the
1391
+ // process-run route directly; Netlify evaluates serverless functions BEFORE
1392
+ // redirects (request-chain step 10 vs 11), and we exclude this path from the
1393
+ // \`server\` /* catch-all so only THIS function matches it no ambiguous
1394
+ // function-vs-function order.
1323
1395
  background: true,
1324
- path: ${JSON.stringify([AGENT_CHAT_PROCESS_RUN_PATH])},
1396
+ path: PROCESS_RUN_PATH,
1325
1397
  nodeBundler: "none",
1326
1398
  includedFiles: ["**"],
1327
1399
  preferStatic: false,
1328
1400
  };
1329
1401
  `;
1330
1402
  fs.writeFileSync(path.join(dest, `${backgroundName}.mjs`), entry);
1331
- console.log(`[build] Emitted durable-background function "${backgroundName}" ` +
1332
- `(path ${AGENT_CHAT_PROCESS_RUN_PATH}). REQUIRES real-deploy verification ` +
1333
- `of Netlify async routing see docs/design/durable-agent-runs.md.`);
1403
+ console.log(`[build] Emitted durable-background function "${backgroundName}" into the ` +
1404
+ `scanned dir .netlify/functions-internal with config { background:true, ` +
1405
+ `path:"${AGENT_CHAT_PROCESS_RUN_PATH}" } and excluded that path from the ` +
1406
+ `server /* catch-all. REQUIRES real-deploy verification of Netlify async ` +
1407
+ `(202) invocation — see docs/design/durable-agent-runs.md.`);
1408
+ }
1409
+ /**
1410
+ * Append `AGENT_CHAT_PROCESS_RUN_PATH` to the Nitro `server` function's
1411
+ * `config.excludedPath` so its `/*` catch-all does NOT match the process-run
1412
+ * path. That guarantees the async background function (which declares
1413
+ * `config.path = AGENT_CHAT_PROCESS_RUN_PATH`) is the ONLY function that matches
1414
+ * that path — Netlify does not define a winner when two serverless functions
1415
+ * both match, so we make the match unambiguous instead of relying on order.
1416
+ *
1417
+ * The Nitro-generated `server/server.mjs` is small and deterministic:
1418
+ * export { default } from "./main.mjs";
1419
+ * export const config = { ... excludedPath: ["/.netlify/*"], ... };
1420
+ * We parse the `excludedPath: [...]` array literal and add our path if absent.
1421
+ * If the shape ever changes and we can't find/parse it, we log and leave the
1422
+ * file untouched (the inline-40s fallback still keeps chat working).
1423
+ */
1424
+ function excludeProcessRunPathFromServerCatchAll(serverDir) {
1425
+ const serverEntry = path.join(serverDir, "server.mjs");
1426
+ if (!fs.existsSync(serverEntry)) {
1427
+ console.warn("[build] Durable-background: server/server.mjs not found; cannot exclude " +
1428
+ `${AGENT_CHAT_PROCESS_RUN_PATH} from the /* catch-all.`);
1429
+ return;
1430
+ }
1431
+ const original = fs.readFileSync(serverEntry, "utf8");
1432
+ if (original.includes(AGENT_CHAT_PROCESS_RUN_PATH)) {
1433
+ // Already excluded (idempotent — emit may run on a re-used output tree).
1434
+ return;
1435
+ }
1436
+ const excludedPathRe = /excludedPath:\s*\[([^\]]*)\]/;
1437
+ const match = original.match(excludedPathRe);
1438
+ const quotedPath = JSON.stringify(AGENT_CHAT_PROCESS_RUN_PATH);
1439
+ if (match) {
1440
+ const existing = match[1].trim();
1441
+ const next = existing
1442
+ ? `excludedPath: [${existing.replace(/,\s*$/, "")}, ${quotedPath}]`
1443
+ : `excludedPath: [${quotedPath}]`;
1444
+ fs.writeFileSync(serverEntry, original.replace(excludedPathRe, next));
1445
+ return;
1446
+ }
1447
+ // No existing `excludedPath` — inject one into the config object. Match the
1448
+ // `path: "/*"` line and add `excludedPath` right after it.
1449
+ const pathLineRe = /(path:\s*("\/\*"|'\/\*'),?)/;
1450
+ if (pathLineRe.test(original)) {
1451
+ fs.writeFileSync(serverEntry, original.replace(pathLineRe, `$1\n excludedPath: [${quotedPath}],`));
1452
+ return;
1453
+ }
1454
+ console.warn("[build] Durable-background: could not locate excludedPath/path in " +
1455
+ "server/server.mjs; leaving the /* catch-all unchanged (the background " +
1456
+ "function may be shadowed — the inline-40s fallback still applies).");
1334
1457
  }
1335
1458
  function copyInstalledLibsqlNativePackages(serverDir) {
1336
1459
  if (!serverDir || !fs.existsSync(serverDir))