@keystrokehq/cli 0.1.16 → 0.1.18

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { M as entryIdFromFile, N as readKeystrokeIgnoreDirective, P as shouldSkipKeystrokeModuleFile, k as packAssetDirs, r as buildStoredRouteManifestForProject } from "./dist-BW3AMCud.mjs";
2
+ import { M as entryIdFromFile, N as readKeystrokeIgnoreDirective, P as shouldSkipKeystrokeModuleFile, k as packAssetDirs, r as buildStoredRouteManifestForProject } from "./dist-BaOUOcKY.mjs";
3
3
  import { isBuiltin } from "node:module";
4
4
  import { dirname, join, relative, resolve, sep } from "node:path";
5
5
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
@@ -538,7 +538,7 @@ async function buildApp(options = {}) {
538
538
  ignoredFiles: walked.ignoredFiles
539
539
  }));
540
540
  if (emitManifest) {
541
- const { emitStoredRouteManifestForProject } = await import("./dist-c4WWC9_F.mjs");
541
+ const { emitStoredRouteManifestForProject } = await import("./dist-Wchlpwl7.mjs");
542
542
  await emitStoredRouteManifestForProject(root);
543
543
  }
544
544
  } finally {
@@ -563,4 +563,4 @@ async function watchApp(options = {}) {
563
563
  //#endregion
564
564
  export { buildApp, buildFilteredApp, resolveRuntimeBuildArtifact, watchApp };
565
565
 
566
- //# sourceMappingURL=dist-PBiyADK0.mjs.map
566
+ //# sourceMappingURL=dist-DR8DYUc4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"dist-PBiyADK0.mjs","names":["toPosix"],"sources":["../../../packages/build/dist/walk-project-eZ95LOUW.mjs","../../../packages/tsdown-config/deps.js","../../../packages/tsdown-config/index.js","../../../packages/build/dist/index.mjs"],"sourcesContent":["import { readFileSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { entryIdFromFile, readKeystrokeIgnoreDirective, shouldSkipKeystrokeModuleFile } from \"@keystrokehq/manifest/discovery\";\nimport { fileURLToPath } from \"node:url\";\n//#region src/ignore-guard-plugin.ts\nfunction toPosix$1(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction projectRelativePath(root, filePath) {\n\treturn toPosix$1(relative(root, normalizeBuildFilePath(filePath)));\n}\n/** Normalize paths so /var and /private/var compare equal on macOS. */\nfunction normalizeBuildFilePath(filePath) {\n\tconst absolute = resolve(filePath);\n\ttry {\n\t\treturn realpathSync.native(absolute);\n\t} catch {\n\t\treturn absolute;\n\t}\n}\nfunction normalizeModuleId(id, root) {\n\tif (id.startsWith(\"\\0\")) return null;\n\tconst normalized = normalizeBuildFilePath(id.startsWith(\"file://\") ? fileURLToPath(id) : id);\n\tif (!normalized.startsWith(normalizeBuildFilePath(root))) return null;\n\treturn normalized;\n}\nfunction formatImportGuardError(root, ignoredPath, importer) {\n\tconst ignored = projectRelativePath(root, ignoredPath);\n\tif (importer) return `Cannot import \"${ignored}\" (@keystroke ignore) from \"${projectRelativePath(root, importer)}\". Remove the directive or stop importing it from a shipped module.`;\n\treturn `Cannot import \"${ignored}\" (@keystroke ignore). Remove the directive or stop importing it from a shipped module.`;\n}\n/** Throw when a built module imports a `@keystroke ignore` source file. */\nfunction keystrokeIgnoreGuardPlugin(options) {\n\tconst root = normalizeBuildFilePath(options.root);\n\tconst ignoredFiles = new Set(options.ignoredFiles.map((filePath) => normalizeBuildFilePath(filePath)));\n\tfunction assertNotIgnored(filePath, importer) {\n\t\tconst normalized = normalizeBuildFilePath(filePath);\n\t\tif (!ignoredFiles.has(normalized)) return;\n\t\tthrow new Error(formatImportGuardError(root, normalized, importer));\n\t}\n\treturn {\n\t\tname: \"keystroke-ignore-guard\",\n\t\tasync resolveId(source, importer, resolveOptions) {\n\t\t\tif (resolveOptions?.isEntry || !importer) return null;\n\t\t\tconst resolved = await this.resolve(source, importer, {\n\t\t\t\t...resolveOptions,\n\t\t\t\tskipSelf: true\n\t\t\t});\n\t\t\tif (!resolved) return null;\n\t\t\tassertNotIgnored(typeof resolved === \"string\" ? resolved : resolved.id, importer);\n\t\t\treturn null;\n\t\t},\n\t\tload(id) {\n\t\t\tconst normalized = normalizeModuleId(id, root);\n\t\t\tif (!normalized) return null;\n\t\t\tassertNotIgnored(normalized);\n\t\t\treturn null;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/walk-project.ts\nconst IGNORED_DIRS = new Set([\n\t\"node_modules\",\n\t\"dist\",\n\t\".git\",\n\t\".turbo\",\n\t\"build\",\n\t\"coverage\",\n\t\".keystroke\",\n\t\".cache\",\n\t\"tmp\"\n]);\nconst IGNORED_ENV_FILE = /\\.env/;\nconst IGNORED_LOG_FILE = /\\.log$/;\nfunction isIgnoredFile(name) {\n\treturn IGNORED_ENV_FILE.test(name) || IGNORED_LOG_FILE.test(name);\n}\nfunction toPosix(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction isProbablyBinary(buffer) {\n\tconst sampleLength = Math.min(buffer.length, 8e3);\n\tfor (let index = 0; index < sampleLength; index += 1) if (buffer[index] === 0) return true;\n\treturn false;\n}\nfunction classifyBuildEntry(root, srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(root, filePath));\n\tconst agentsPrefix = `${toPosix(relative(root, join(srcRoot, \"agents\")))}/`;\n\tconst workflowsPrefix = `${toPosix(relative(root, join(srcRoot, \"workflows\")))}/`;\n\tconst triggersPrefix = `${toPosix(relative(root, join(srcRoot, \"triggers\")))}/`;\n\tif (relativePath.startsWith(agentsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"agents\"), filePath, { nestedEntry: \"agent\" });\n\t\treturn id ? {\n\t\t\tentryKey: `agents/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(workflowsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"workflows\"), filePath, { nestedEntry: \"workflow\" });\n\t\treturn id ? {\n\t\t\tentryKey: `workflows/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(triggersPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"triggers\"), filePath, { nestedEntry: \"trigger\" });\n\t\treturn id ? {\n\t\t\tentryKey: `triggers/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\treturn null;\n}\nfunction shouldSkipIgnoredModule(filePath, phase) {\n\treturn shouldSkipKeystrokeModuleFile(readKeystrokeIgnoreDirective(filePath), phase);\n}\nfunction isSrcTypeScriptFile(srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(srcRoot, filePath));\n\tif (relativePath.startsWith(\"..\")) return false;\n\treturn /\\.(ts|mts)$/.test(relativePath);\n}\nfunction walkTree(root, dir, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals) {\n\tfor (const name of readdirSync(dir).sort()) {\n\t\tif (collectSources && (sourceFiles.length >= 2e3 || totals.bytes >= 8388608)) return;\n\t\tconst absolute = join(dir, name);\n\t\tconst stats = statSync(absolute);\n\t\tif (stats.isDirectory()) {\n\t\t\tif (IGNORED_DIRS.has(name)) continue;\n\t\t\twalkTree(root, absolute, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!stats.isFile()) continue;\n\t\tconst isUnderSrc = isSrcTypeScriptFile(srcRoot, absolute);\n\t\tconst skipIgnored = isUnderSrc ? shouldSkipIgnoredModule(absolute, phase) : false;\n\t\tif (isUnderSrc && skipIgnored) ignoredFiles.push(normalizeBuildFilePath(absolute));\n\t\tconst buildEntry = classifyBuildEntry(root, srcRoot, absolute);\n\t\tif (buildEntry && !skipIgnored) buildEntries[buildEntry.entryKey] = buildEntry.entryPath;\n\t\tif (!collectSources) continue;\n\t\tif (stats.size > 262144 || isIgnoredFile(name)) continue;\n\t\tconst buffer = readFileSync(absolute);\n\t\tif (isProbablyBinary(buffer)) continue;\n\t\ttotals.bytes += buffer.byteLength;\n\t\tsourceFiles.push({\n\t\t\tpath: toPosix(relative(root, absolute)),\n\t\t\tcontents: buffer.toString(\"utf8\"),\n\t\t\thash: createHash(\"sha256\").update(buffer).digest(\"hex\")\n\t\t});\n\t}\n}\n/**\n* One full-tree walk of the project: classifies tsdown entries and optionally\n* collects deploy source files (path + contents + hash) under snapshot limits.\n*/\nfunction walkProject(root, srcDirOrOptions = \"src\", maybeOptions) {\n\tconst srcDir = typeof srcDirOrOptions === \"string\" ? srcDirOrOptions : srcDirOrOptions.srcDir ?? \"src\";\n\tconst options = typeof srcDirOrOptions === \"string\" ? maybeOptions ?? {} : srcDirOrOptions;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst sourceFiles = [];\n\tconst buildEntries = {};\n\tconst ignoredFiles = [];\n\twalkTree(root, root, join(root, srcDir), phase, collectSources, sourceFiles, buildEntries, ignoredFiles, { bytes: 0 });\n\treturn {\n\t\tsourceFiles,\n\t\tbuildEntries,\n\t\tignoredFiles\n\t};\n}\n//#endregion\nexport { keystrokeIgnoreGuardPlugin as n, walkProject as t };\n\n//# sourceMappingURL=walk-project-eZ95LOUW.mjs.map","import { isBuiltin } from \"node:module\";\n\n/** Native addons kept external — resolved from the CLI runtime at app start. */\nexport const NATIVE_RUNTIME_DEPS = [\"pg\", \"better-sqlite3\", \"@parcel/watcher\"];\n\n/**\n * Framework/runtime `@keystrokehq/*` shipped in the project-server image, so user-app builds\n * keep them external and resolve them from the runtime at boot. Everything else under the scope\n * (Composio catalog integrations like `@keystrokehq/posthog`, …) is bundled into the artifact.\n *\n * This set MUST equal the `@keystrokehq/*` dependency closure of `@keystrokehq/project-runtime`\n * (the deploy image) — `deps.test.ts` enforces it. To change what stays external, change what the\n * runtime image depends on; do not edit this list by hand. `exa` is the only integration\n * package the framework imports directly (web search); `gateway` ships Slack and other channel\n * adapters in the runtime image.\n */\nexport const RUNTIME_KEYSTROKE_PACKAGES = new Set([\n \"access-control\",\n \"action\",\n \"agent\",\n \"app\",\n \"auth\",\n \"build\",\n \"config\",\n \"credentials\",\n \"database\",\n \"exa\",\n \"gateway\",\n \"hosting\",\n \"http\",\n \"keystroke\",\n \"manifest\",\n \"mcp\",\n \"memory\",\n \"oauth\",\n \"platform-database\",\n \"project-runtime\",\n \"projects\",\n \"runtime\",\n \"sandbox\",\n \"scheduler\",\n \"sdk\",\n \"secrets\",\n \"shared\",\n \"storage\",\n \"tracing\",\n \"trigger\",\n \"tsdown-config\",\n \"web-search\",\n \"worker\",\n \"workflow\",\n]);\n\n/** Matches framework/runtime `@keystrokehq/*` kept external during user-app builds. */\nexport const FRAMEWORK_KEYSTROKE_EXTERNAL = new RegExp(\n `^@keystrokehq\\\\/(?:${[...RUNTIME_KEYSTROKE_PACKAGES].sort().join(\"|\")})(?:\\\\/|$)`,\n);\n\nfunction keystrokePackageName(name) {\n if (!name.startsWith(\"@keystrokehq/\")) {\n return null;\n }\n\n return name.slice(\"@keystrokehq/\".length).split(\"/\")[0] ?? null;\n}\n\nfunction isRuntimeKeystrokePackage(name) {\n const pkg = keystrokePackageName(name);\n return pkg !== null && RUNTIME_KEYSTROKE_PACKAGES.has(pkg);\n}\n\n/** Kept external so .d.ts emission does not inline internal/inferred types. */\nexport const LIBRARY_EXTERNAL_DEPS = [\"better-auth\", /^@better-auth\\//, /^better-auth\\//];\n\n/** Non-auth runtime deps kept external for published entry bundles (platform, etc.). */\nexport const BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS = [\n ...NATIVE_RUNTIME_DEPS,\n \"dockerode\",\n \"ssh2\",\n \"cpu-features\",\n \"microsandbox\",\n /^@aws-sdk\\//,\n /^@napi-rs\\//,\n \"hono\",\n /^@hono\\//,\n \"undici\",\n];\n\n/** Kept external when bundling published entry points (cli, keystroke, platform). */\nexport const BUNDLED_ENTRY_EXTERNAL_DEPS = [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...LIBRARY_EXTERNAL_DEPS,\n];\n\n/** Bundle into CLI — device login uses Better Auth client only. */\nexport const BETTER_AUTH_CLIENT_BUNDLE_PATTERNS = [\n /^better-auth\\/client$/,\n /^better-auth\\/client\\//,\n];\n\n/** Server adapters and root entry — must not ship in the CLI bundle. */\nexport const BETTER_AUTH_SERVER_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^@better-auth\\//,\n /^better-auth\\/(?!client(\\/|$)).+/,\n];\n\nexport function isNativeRuntimeDep(id) {\n return NATIVE_RUNTIME_DEPS.some((dep) => id === dep || id.startsWith(`${dep}/`));\n}\n\nfunction packageName(id) {\n if (id.startsWith(\"@\")) {\n const [scope, name] = id.split(\"/\");\n return name ? `${scope}/${name}` : id;\n }\n\n return id.split(\"/\")[0] ?? id;\n}\n\nfunction isRuntimeExternal(id) {\n const name = packageName(id);\n if (isNativeRuntimeDep(name)) {\n return true;\n }\n\n if (name.startsWith(\"@keystrokehq/\")) {\n return isRuntimeKeystrokePackage(name);\n }\n\n if (name === \"better-auth\" || name.startsWith(\"@better-auth/\")) {\n return true;\n }\n\n return false;\n}\n\n/** Library packages resolve npm deps from node_modules at runtime. */\nexport function libraryBuildDepsConfig() {\n return {\n alwaysBundle: (_id) => null,\n neverBundle: [...NATIVE_RUNTIME_DEPS, /^@keystrokehq\\//, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Bundle npm deps into dist; resolve @keystrokehq/* and natives from the runtime. */\nexport function userAppBuildDepsConfig() {\n return {\n alwaysBundle: (id, _importer) => {\n if (id.startsWith(\".\") || id.startsWith(\"/\") || isBuiltin(id)) {\n return null;\n }\n\n return isRuntimeExternal(id) ? null : true;\n },\n neverBundle: [...NATIVE_RUNTIME_DEPS, FRAMEWORK_KEYSTROKE_EXTERNAL, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/**\n * Published entry packages (cli, keystroke, platform): declare bundled @keystrokehq/*\n * in dependencies (changesets release graph ignores devDependencies). Inlining is\n * driven by alwaysBundle below, not by dep kind. Runtime npm deps stay external.\n */\nexport function bundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//],\n neverBundle: [...BUNDLED_ENTRY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Published CLI: inline better-auth client + @better-auth/*; keep server adapters external. */\nexport const BETTER_AUTH_CLI_BUNDLE_PATTERNS = [\n ...BETTER_AUTH_CLIENT_BUNDLE_PATTERNS,\n /^@better-auth\\//,\n];\n\nexport const BETTER_AUTH_CLI_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^better-auth\\/(?!client(\\/|$)).+/,\n /^@better-auth\\/drizzle-adapter/,\n \"drizzle-orm\",\n];\n\n/** Rolldown/tsdown — native bindings; stay in CLI node_modules at runtime. */\nexport const CLI_BUILD_TOOL_EXTERNAL_PATTERNS = [\"tsdown\", \"rolldown\", /^@rolldown\\//, \"tsx\"];\n\n/** CLI: inline better-auth/client; keep server + drizzle adapters external. */\nexport function cliBundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//, ...BETTER_AUTH_CLI_BUNDLE_PATTERNS],\n neverBundle: [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...BETTER_AUTH_CLI_EXTERNAL_PATTERNS,\n ...CLI_BUILD_TOOL_EXTERNAL_PATTERNS,\n ],\n onlyBundle: false,\n };\n}\n","import { bundledEntryDepsConfig, libraryBuildDepsConfig, userAppBuildDepsConfig } from \"./deps.js\";\n\nexport {\n isNativeRuntimeDep,\n NATIVE_RUNTIME_DEPS,\n bundledEntryDepsConfig,\n cliBundledEntryDepsConfig,\n libraryBuildDepsConfig,\n userAppBuildDepsConfig,\n} from \"./deps.js\";\n\nexport const baseTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: libraryBuildDepsConfig(),\n};\n\n/** tsdown config for published bundles (cli, keystroke, platform). */\nexport const bundledEntryTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: bundledEntryDepsConfig(),\n};\n","import { n as keystrokeIgnoreGuardPlugin, t as walkProject } from \"./walk-project-eZ95LOUW.mjs\";\nimport { t as resolveModuleDirs } from \"./resolve-module-dirs-BPHQhRGy.mjs\";\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { packAssetDirs } from \"@keystrokehq/sandbox/files\";\nimport { baseTsdownConfig, userAppBuildDepsConfig } from \"@keystrokehq/tsdown-config\";\nimport { build, mergeConfig } from \"tsdown\";\nimport { buildStoredRouteManifestForProject } from \"@keystrokehq/manifest\";\n//#region src/resolve-runtime-artifact.ts\nfunction packageRoot(nodeModules, scope, name) {\n\tconst direct = scope ? join(nodeModules, scope, name) : join(nodeModules, name);\n\tif (existsSync(join(direct, \"package.json\"))) return direct;\n\tconst pnpmDir = join(nodeModules, \".pnpm\");\n\tif (!existsSync(pnpmDir)) return null;\n\tfor (const entry of readdirSync(pnpmDir)) {\n\t\tconst candidate = scope ? join(pnpmDir, entry, \"node_modules\", scope, name) : join(pnpmDir, entry, \"node_modules\", name);\n\t\tif (existsSync(join(candidate, \"package.json\"))) return candidate;\n\t}\n\treturn null;\n}\n/** Resolve a file shipped with `@keystrokehq/build` inside the CLI runtime. */\nfunction resolveRuntimeBuildArtifact(runtimeNodeModules, relativePath) {\n\tconst pkgRoot = packageRoot(runtimeNodeModules, \"@keystrokehq\", \"build\");\n\tif (!pkgRoot) throw new Error(\"Keystroke runtime is missing @keystrokehq/build\");\n\tconst artifact = join(pkgRoot, relativePath);\n\tif (!existsSync(artifact)) throw new Error(`Keystroke runtime artifact not found: ${relativePath}`);\n\treturn artifact;\n}\n//#endregion\n//#region src/vitest-plugin.ts\nconst ASSETS_MODULE$1 = \"@keystrokehq/assets\";\nconst virtualPrefix = `\\0${ASSETS_MODULE$1}:`;\n/** Vitest plugin resolving `@keystrokehq/assets` from disk. */\nfunction agentAssetsVitestPlugin(appRoot = process.cwd()) {\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE$1) return null;\n\t\t\treturn `${virtualPrefix}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${virtualPrefix}manifest`) return null;\n\t\t\tmanifest ??= packAssetDirs(appRoot);\n\t\t\treturn `export default ${JSON.stringify(manifest)};`;\n\t\t}\n\t};\n}\nfunction findAppRootFromConfig(configFile) {\n\tif (!configFile) return process.cwd();\n\treturn dirname(configFile);\n}\nfunction agentAssetsVitestPluginFromConfig(configFile) {\n\treturn agentAssetsVitestPlugin(findAppRootFromConfig(configFile));\n}\n//#endregion\n//#region src/resolve-build-filter.ts\n/** Resolve exact build-entry keys for a filtered deploy build. */\nfunction resolveBuildFilter(filter, buildEntries) {\n\tif (filter.length === 0) throw new Error(\"At least one --filter entry is required\");\n\tconst matched = {};\n\tfor (const key of [...new Set(filter)]) {\n\t\tconst entryPath = buildEntries[key];\n\t\tif (!entryPath) throw new Error(`Unknown build entry \"${key}\". Use keys like agents/foo or workflows/bar from walkProject.`);\n\t\tmatched[key] = entryPath;\n\t}\n\treturn matched;\n}\n//#endregion\n//#region src/build-filtered.ts\nfunction toPosix(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nfunction distRelativePath(entryKey) {\n\treturn `${entryKey}.mjs`;\n}\nasync function buildSingleEntry(root, entryKey, entryPath, ignoredFiles) {\n\tmkdirSync(join(root, \".keystroke\"), { recursive: true });\n\tconst scratchRoot = mkdtempSync(join(root, \".keystroke\", \"filter-build-\"));\n\tconst outDir = join(scratchRoot, \"dist\");\n\tconst relativePath = distRelativePath(entryKey);\n\tawait build(mergeConfig(baseTsdownConfig, {\n\t\tentry: { [entryKey]: entryPath },\n\t\tformat: [\"esm\"],\n\t\toutDir,\n\t\tclean: true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t})]\n\t}));\n\treturn {\n\t\tscratchRoot,\n\t\trelativePath\n\t};\n}\nasync function manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap) {\n\tconst moduleFile = toPosix(relative(root, entryPath));\n\tconst distPath = join(root, \"dist\", relativePath);\n\tconst distMapPath = `${distPath}.map`;\n\tconst previousDist = existsSync(distPath) ? readFileSync(distPath) : void 0;\n\tconst hadMap = existsSync(distMapPath);\n\tconst previousMap = hadMap ? readFileSync(distMapPath) : void 0;\n\tmkdirSync(dirname(distPath), { recursive: true });\n\twriteFileSync(distPath, contents);\n\tif (sourceMap) writeFileSync(distMapPath, sourceMap);\n\ttry {\n\t\treturn (await buildStoredRouteManifestForProject(root, { reloadModules: true })).entries.filter((entry) => \"moduleFile\" in entry && entry.moduleFile === moduleFile);\n\t} finally {\n\t\tif (previousDist) writeFileSync(distPath, previousDist);\n\t\telse rmSync(distPath, { force: true });\n\t\tif (previousMap) writeFileSync(distMapPath, previousMap);\n\t\telse if (sourceMap || hadMap) rmSync(distMapPath, { force: true });\n\t}\n}\n/** Build selected modules in isolation for a filtered deploy merge. */\nasync function buildFilteredApp(options) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst phase = options.phase ?? \"deploy\";\n\tconst collectSources = options.collectSources ?? false;\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\tconst matched = resolveBuildFilter(options.filter, walked.buildEntries);\n\tconst files = [];\n\tconst manifestEntries = [];\n\ttry {\n\t\tprocess.chdir(root);\n\t\tfor (const [entryKey, entryPath] of Object.entries(matched)) {\n\t\t\tconst { scratchRoot, relativePath } = await buildSingleEntry(root, entryKey, entryPath, walked.ignoredFiles);\n\t\t\ttry {\n\t\t\t\tconst builtPath = join(scratchRoot, \"dist\", relativePath);\n\t\t\t\tconst mapPath = `${builtPath}.map`;\n\t\t\t\tconst contents = readFileSync(builtPath);\n\t\t\t\tconst sourceMap = existsSync(mapPath) ? readFileSync(mapPath) : void 0;\n\t\t\t\tfiles.push({\n\t\t\t\t\tentryKey,\n\t\t\t\t\trelativePath,\n\t\t\t\t\tcontents,\n\t\t\t\t\tsourceMap\n\t\t\t\t});\n\t\t\t\tmanifestEntries.push(...await manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap));\n\t\t\t} finally {\n\t\t\t\trmSync(scratchRoot, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tforce: true\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn {\n\t\tfiles,\n\t\tmanifestEntries,\n\t\tsourceFiles: walked.sourceFiles\n\t};\n}\n//#endregion\n//#region src/index.ts\nconst ASSETS_MODULE = \"@keystrokehq/assets\";\nconst VIRTUAL_PREFIX = `\\0${ASSETS_MODULE}:`;\nfunction renderAssetModule(manifest) {\n\treturn `export default ${JSON.stringify(manifest)};\\n`;\n}\n/** Rolldown plugin: pack src/skills + src/files and expose `@keystrokehq/assets`. */\nfunction agentAssetsPlugin(options) {\n\tconst srcDir = options.srcDir ?? \"src\";\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tbuildStart() {\n\t\t\tmanifest = packAssetDirs(options.root, srcDir);\n\t\t},\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE) return null;\n\t\t\treturn `${VIRTUAL_PREFIX}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${VIRTUAL_PREFIX}manifest` || !manifest) return null;\n\t\t\treturn renderAssetModule(manifest);\n\t\t},\n\t\tbuildEnd() {\n\t\t\tif (!manifest) return;\n\t\t\tconst outDir = join(options.root, options.outDir ?? \"dist\", \".keystroke\");\n\t\t\tmkdirSync(outDir, { recursive: true });\n\t\t\twriteFileSync(join(outDir, \"assets.mjs\"), renderAssetModule(manifest));\n\t\t}\n\t};\n}\n/** Full tsdown config for user keystroke apps (config + discovered modules only). */\nfunction createAppBuildConfig(options = {}, walked) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst outDir = options.outDir ?? \"dist\";\n\tconst configEntry = existsSync(join(root, \"keystroke.config.ts\")) ? join(root, \"keystroke.config.ts\") : void 0;\n\tconst walkedResult = walked ?? walkProject(root, {\n\t\tsrcDir,\n\t\tphase: options.phase\n\t});\n\tconst discovered = walkedResult.buildEntries;\n\tconst ignoredFiles = walkedResult.ignoredFiles;\n\tconst entries = {\n\t\t...configEntry ? { config: configEntry } : {},\n\t\t...discovered\n\t};\n\tif (Object.keys(entries).length === 0) throw new Error(\"Nothing to build — add keystroke.config.ts or modules under src/\");\n\treturn mergeConfig(baseTsdownConfig, {\n\t\tentry: entries,\n\t\tformat: [\"esm\"],\n\t\toutDir: join(root, outDir),\n\t\tclean: options.clean ?? true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t}), agentAssetsPlugin({\n\t\t\troot,\n\t\t\tsrcDir,\n\t\t\toutDir\n\t\t})]\n\t});\n}\n/** Build user agents, workflows, triggers, and config to `dist/`. */\nasync function buildApp(options = {}) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst emitManifest = options.emitManifest ?? true;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\ttry {\n\t\tprocess.chdir(root);\n\t\tawait build(createAppBuildConfig({\n\t\t\t...options,\n\t\t\troot\n\t\t}, {\n\t\t\tbuildEntries: walked.buildEntries,\n\t\t\tignoredFiles: walked.ignoredFiles\n\t\t}));\n\t\tif (emitManifest) {\n\t\t\tconst { emitStoredRouteManifestForProject } = await import(\"@keystrokehq/manifest\");\n\t\t\tawait emitStoredRouteManifestForProject(root);\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn { sourceFiles: walked.sourceFiles };\n}\n/**\n* Watch `src/` and rebuild `dist/` on change.\n*\n* NOT true hot reload — each change runs a full tsdown rebuild. Callers should\n* restart the API server in `onRebuild` so discovery picks up new/changed modules.\n*/\nasync function watchApp(options = {}) {\n\tconst { runWatchApp } = await import(\"./watch-app-DTIeKrbl.mjs\");\n\tawait runWatchApp((watchOptions) => buildApp({\n\t\t...watchOptions,\n\t\temitManifest: false,\n\t\tcollectSources: false\n\t}), options);\n}\n//#endregion\nexport { agentAssetsVitestPlugin, agentAssetsVitestPluginFromConfig, buildApp, buildFilteredApp, createAppBuildConfig, resolveBuildFilter, resolveModuleDirs, resolveRuntimeBuildArtifact, watchApp };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}
1
+ {"version":3,"file":"dist-DR8DYUc4.mjs","names":["toPosix"],"sources":["../../../packages/build/dist/walk-project-eZ95LOUW.mjs","../../../packages/tsdown-config/deps.js","../../../packages/tsdown-config/index.js","../../../packages/build/dist/index.mjs"],"sourcesContent":["import { readFileSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { entryIdFromFile, readKeystrokeIgnoreDirective, shouldSkipKeystrokeModuleFile } from \"@keystrokehq/manifest/discovery\";\nimport { fileURLToPath } from \"node:url\";\n//#region src/ignore-guard-plugin.ts\nfunction toPosix$1(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction projectRelativePath(root, filePath) {\n\treturn toPosix$1(relative(root, normalizeBuildFilePath(filePath)));\n}\n/** Normalize paths so /var and /private/var compare equal on macOS. */\nfunction normalizeBuildFilePath(filePath) {\n\tconst absolute = resolve(filePath);\n\ttry {\n\t\treturn realpathSync.native(absolute);\n\t} catch {\n\t\treturn absolute;\n\t}\n}\nfunction normalizeModuleId(id, root) {\n\tif (id.startsWith(\"\\0\")) return null;\n\tconst normalized = normalizeBuildFilePath(id.startsWith(\"file://\") ? fileURLToPath(id) : id);\n\tif (!normalized.startsWith(normalizeBuildFilePath(root))) return null;\n\treturn normalized;\n}\nfunction formatImportGuardError(root, ignoredPath, importer) {\n\tconst ignored = projectRelativePath(root, ignoredPath);\n\tif (importer) return `Cannot import \"${ignored}\" (@keystroke ignore) from \"${projectRelativePath(root, importer)}\". Remove the directive or stop importing it from a shipped module.`;\n\treturn `Cannot import \"${ignored}\" (@keystroke ignore). Remove the directive or stop importing it from a shipped module.`;\n}\n/** Throw when a built module imports a `@keystroke ignore` source file. */\nfunction keystrokeIgnoreGuardPlugin(options) {\n\tconst root = normalizeBuildFilePath(options.root);\n\tconst ignoredFiles = new Set(options.ignoredFiles.map((filePath) => normalizeBuildFilePath(filePath)));\n\tfunction assertNotIgnored(filePath, importer) {\n\t\tconst normalized = normalizeBuildFilePath(filePath);\n\t\tif (!ignoredFiles.has(normalized)) return;\n\t\tthrow new Error(formatImportGuardError(root, normalized, importer));\n\t}\n\treturn {\n\t\tname: \"keystroke-ignore-guard\",\n\t\tasync resolveId(source, importer, resolveOptions) {\n\t\t\tif (resolveOptions?.isEntry || !importer) return null;\n\t\t\tconst resolved = await this.resolve(source, importer, {\n\t\t\t\t...resolveOptions,\n\t\t\t\tskipSelf: true\n\t\t\t});\n\t\t\tif (!resolved) return null;\n\t\t\tassertNotIgnored(typeof resolved === \"string\" ? resolved : resolved.id, importer);\n\t\t\treturn null;\n\t\t},\n\t\tload(id) {\n\t\t\tconst normalized = normalizeModuleId(id, root);\n\t\t\tif (!normalized) return null;\n\t\t\tassertNotIgnored(normalized);\n\t\t\treturn null;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/walk-project.ts\nconst IGNORED_DIRS = new Set([\n\t\"node_modules\",\n\t\"dist\",\n\t\".git\",\n\t\".turbo\",\n\t\"build\",\n\t\"coverage\",\n\t\".keystroke\",\n\t\".cache\",\n\t\"tmp\"\n]);\nconst IGNORED_ENV_FILE = /\\.env/;\nconst IGNORED_LOG_FILE = /\\.log$/;\nfunction isIgnoredFile(name) {\n\treturn IGNORED_ENV_FILE.test(name) || IGNORED_LOG_FILE.test(name);\n}\nfunction toPosix(path) {\n\treturn path.split(sep).join(\"/\");\n}\nfunction isProbablyBinary(buffer) {\n\tconst sampleLength = Math.min(buffer.length, 8e3);\n\tfor (let index = 0; index < sampleLength; index += 1) if (buffer[index] === 0) return true;\n\treturn false;\n}\nfunction classifyBuildEntry(root, srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(root, filePath));\n\tconst agentsPrefix = `${toPosix(relative(root, join(srcRoot, \"agents\")))}/`;\n\tconst workflowsPrefix = `${toPosix(relative(root, join(srcRoot, \"workflows\")))}/`;\n\tconst triggersPrefix = `${toPosix(relative(root, join(srcRoot, \"triggers\")))}/`;\n\tif (relativePath.startsWith(agentsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"agents\"), filePath, { nestedEntry: \"agent\" });\n\t\treturn id ? {\n\t\t\tentryKey: `agents/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(workflowsPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"workflows\"), filePath, { nestedEntry: \"workflow\" });\n\t\treturn id ? {\n\t\t\tentryKey: `workflows/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\tif (relativePath.startsWith(triggersPrefix) && /\\.(ts|mts)$/.test(relativePath) && !/\\.(int\\.)?test\\.(ts|mts)$/.test(relativePath)) {\n\t\tconst id = entryIdFromFile(join(srcRoot, \"triggers\"), filePath, { nestedEntry: \"trigger\" });\n\t\treturn id ? {\n\t\t\tentryKey: `triggers/${id}`,\n\t\t\tentryPath: filePath\n\t\t} : null;\n\t}\n\treturn null;\n}\nfunction shouldSkipIgnoredModule(filePath, phase) {\n\treturn shouldSkipKeystrokeModuleFile(readKeystrokeIgnoreDirective(filePath), phase);\n}\nfunction isSrcTypeScriptFile(srcRoot, filePath) {\n\tconst relativePath = toPosix(relative(srcRoot, filePath));\n\tif (relativePath.startsWith(\"..\")) return false;\n\treturn /\\.(ts|mts)$/.test(relativePath);\n}\nfunction walkTree(root, dir, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals) {\n\tfor (const name of readdirSync(dir).sort()) {\n\t\tif (collectSources && (sourceFiles.length >= 2e3 || totals.bytes >= 8388608)) return;\n\t\tconst absolute = join(dir, name);\n\t\tconst stats = statSync(absolute);\n\t\tif (stats.isDirectory()) {\n\t\t\tif (IGNORED_DIRS.has(name)) continue;\n\t\t\twalkTree(root, absolute, srcRoot, phase, collectSources, sourceFiles, buildEntries, ignoredFiles, totals);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!stats.isFile()) continue;\n\t\tconst isUnderSrc = isSrcTypeScriptFile(srcRoot, absolute);\n\t\tconst skipIgnored = isUnderSrc ? shouldSkipIgnoredModule(absolute, phase) : false;\n\t\tif (isUnderSrc && skipIgnored) ignoredFiles.push(normalizeBuildFilePath(absolute));\n\t\tconst buildEntry = classifyBuildEntry(root, srcRoot, absolute);\n\t\tif (buildEntry && !skipIgnored) buildEntries[buildEntry.entryKey] = buildEntry.entryPath;\n\t\tif (!collectSources) continue;\n\t\tif (stats.size > 262144 || isIgnoredFile(name)) continue;\n\t\tconst buffer = readFileSync(absolute);\n\t\tif (isProbablyBinary(buffer)) continue;\n\t\ttotals.bytes += buffer.byteLength;\n\t\tsourceFiles.push({\n\t\t\tpath: toPosix(relative(root, absolute)),\n\t\t\tcontents: buffer.toString(\"utf8\"),\n\t\t\thash: createHash(\"sha256\").update(buffer).digest(\"hex\")\n\t\t});\n\t}\n}\n/**\n* One full-tree walk of the project: classifies tsdown entries and optionally\n* collects deploy source files (path + contents + hash) under snapshot limits.\n*/\nfunction walkProject(root, srcDirOrOptions = \"src\", maybeOptions) {\n\tconst srcDir = typeof srcDirOrOptions === \"string\" ? srcDirOrOptions : srcDirOrOptions.srcDir ?? \"src\";\n\tconst options = typeof srcDirOrOptions === \"string\" ? maybeOptions ?? {} : srcDirOrOptions;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst sourceFiles = [];\n\tconst buildEntries = {};\n\tconst ignoredFiles = [];\n\twalkTree(root, root, join(root, srcDir), phase, collectSources, sourceFiles, buildEntries, ignoredFiles, { bytes: 0 });\n\treturn {\n\t\tsourceFiles,\n\t\tbuildEntries,\n\t\tignoredFiles\n\t};\n}\n//#endregion\nexport { keystrokeIgnoreGuardPlugin as n, walkProject as t };\n\n//# sourceMappingURL=walk-project-eZ95LOUW.mjs.map","import { isBuiltin } from \"node:module\";\n\n/** Native addons kept external — resolved from the CLI runtime at app start. */\nexport const NATIVE_RUNTIME_DEPS = [\"pg\", \"better-sqlite3\", \"@parcel/watcher\"];\n\n/**\n * Framework/runtime `@keystrokehq/*` shipped in the project-server image, so user-app builds\n * keep them external and resolve them from the runtime at boot. Everything else under the scope\n * (Composio catalog integrations like `@keystrokehq/posthog`, …) is bundled into the artifact.\n *\n * This set MUST equal the `@keystrokehq/*` dependency closure of `@keystrokehq/project-runtime`\n * (the deploy image) — `deps.test.ts` enforces it. To change what stays external, change what the\n * runtime image depends on; do not edit this list by hand. `exa` is the only integration\n * package the framework imports directly (web search); `gateway` ships Slack and other channel\n * adapters in the runtime image.\n */\nexport const RUNTIME_KEYSTROKE_PACKAGES = new Set([\n \"access-control\",\n \"action\",\n \"agent\",\n \"app\",\n \"auth\",\n \"build\",\n \"config\",\n \"credentials\",\n \"database\",\n \"exa\",\n \"gateway\",\n \"hosting\",\n \"http\",\n \"keystroke\",\n \"manifest\",\n \"mcp\",\n \"memory\",\n \"oauth\",\n \"platform-database\",\n \"project-runtime\",\n \"projects\",\n \"runtime\",\n \"sandbox\",\n \"scheduler\",\n \"sdk\",\n \"secrets\",\n \"shared\",\n \"storage\",\n \"tracing\",\n \"trigger\",\n \"tsdown-config\",\n \"web-search\",\n \"worker\",\n \"workflow\",\n]);\n\n/** Matches framework/runtime `@keystrokehq/*` kept external during user-app builds. */\nexport const FRAMEWORK_KEYSTROKE_EXTERNAL = new RegExp(\n `^@keystrokehq\\\\/(?:${[...RUNTIME_KEYSTROKE_PACKAGES].sort().join(\"|\")})(?:\\\\/|$)`,\n);\n\nfunction keystrokePackageName(name) {\n if (!name.startsWith(\"@keystrokehq/\")) {\n return null;\n }\n\n return name.slice(\"@keystrokehq/\".length).split(\"/\")[0] ?? null;\n}\n\nfunction isRuntimeKeystrokePackage(name) {\n const pkg = keystrokePackageName(name);\n return pkg !== null && RUNTIME_KEYSTROKE_PACKAGES.has(pkg);\n}\n\n/** Kept external so .d.ts emission does not inline internal/inferred types. */\nexport const LIBRARY_EXTERNAL_DEPS = [\"better-auth\", /^@better-auth\\//, /^better-auth\\//];\n\n/** Non-auth runtime deps kept external for published entry bundles (platform, etc.). */\nexport const BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS = [\n ...NATIVE_RUNTIME_DEPS,\n \"dockerode\",\n \"ssh2\",\n \"cpu-features\",\n \"microsandbox\",\n /^@aws-sdk\\//,\n /^@napi-rs\\//,\n \"hono\",\n /^@hono\\//,\n \"undici\",\n];\n\n/** Kept external when bundling published entry points (cli, keystroke, platform). */\nexport const BUNDLED_ENTRY_EXTERNAL_DEPS = [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...LIBRARY_EXTERNAL_DEPS,\n];\n\n/** Bundle into CLI — device login uses Better Auth client only. */\nexport const BETTER_AUTH_CLIENT_BUNDLE_PATTERNS = [\n /^better-auth\\/client$/,\n /^better-auth\\/client\\//,\n];\n\n/** Server adapters and root entry — must not ship in the CLI bundle. */\nexport const BETTER_AUTH_SERVER_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^@better-auth\\//,\n /^better-auth\\/(?!client(\\/|$)).+/,\n];\n\nexport function isNativeRuntimeDep(id) {\n return NATIVE_RUNTIME_DEPS.some((dep) => id === dep || id.startsWith(`${dep}/`));\n}\n\nfunction packageName(id) {\n if (id.startsWith(\"@\")) {\n const [scope, name] = id.split(\"/\");\n return name ? `${scope}/${name}` : id;\n }\n\n return id.split(\"/\")[0] ?? id;\n}\n\nfunction isRuntimeExternal(id) {\n const name = packageName(id);\n if (isNativeRuntimeDep(name)) {\n return true;\n }\n\n if (name.startsWith(\"@keystrokehq/\")) {\n return isRuntimeKeystrokePackage(name);\n }\n\n if (name === \"better-auth\" || name.startsWith(\"@better-auth/\")) {\n return true;\n }\n\n return false;\n}\n\n/** Library packages resolve npm deps from node_modules at runtime. */\nexport function libraryBuildDepsConfig() {\n return {\n alwaysBundle: (_id) => null,\n neverBundle: [...NATIVE_RUNTIME_DEPS, /^@keystrokehq\\//, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Bundle npm deps into dist; resolve @keystrokehq/* and natives from the runtime. */\nexport function userAppBuildDepsConfig() {\n return {\n alwaysBundle: (id, _importer) => {\n if (id.startsWith(\".\") || id.startsWith(\"/\") || isBuiltin(id)) {\n return null;\n }\n\n return isRuntimeExternal(id) ? null : true;\n },\n neverBundle: [...NATIVE_RUNTIME_DEPS, FRAMEWORK_KEYSTROKE_EXTERNAL, ...LIBRARY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/**\n * Published entry packages (cli, keystroke, platform): declare bundled @keystrokehq/*\n * in dependencies (changesets release graph ignores devDependencies). Inlining is\n * driven by alwaysBundle below, not by dep kind. Runtime npm deps stay external.\n */\nexport function bundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//],\n neverBundle: [...BUNDLED_ENTRY_EXTERNAL_DEPS],\n onlyBundle: false,\n };\n}\n\n/** Published CLI: inline better-auth client + @better-auth/*; keep server adapters external. */\nexport const BETTER_AUTH_CLI_BUNDLE_PATTERNS = [\n ...BETTER_AUTH_CLIENT_BUNDLE_PATTERNS,\n /^@better-auth\\//,\n];\n\nexport const BETTER_AUTH_CLI_EXTERNAL_PATTERNS = [\n /^better-auth$/,\n /^better-auth\\/(?!client(\\/|$)).+/,\n /^@better-auth\\/drizzle-adapter/,\n \"drizzle-orm\",\n];\n\n/** Rolldown/tsdown — native bindings; stay in CLI node_modules at runtime. */\nexport const CLI_BUILD_TOOL_EXTERNAL_PATTERNS = [\"tsdown\", \"rolldown\", /^@rolldown\\//, \"tsx\"];\n\n/** CLI: inline better-auth/client; keep server + drizzle adapters external. */\nexport function cliBundledEntryDepsConfig() {\n return {\n alwaysBundle: [/^@keystrokehq\\//, ...BETTER_AUTH_CLI_BUNDLE_PATTERNS],\n neverBundle: [\n ...BUNDLED_ENTRY_RUNTIME_EXTERNAL_DEPS,\n ...BETTER_AUTH_CLI_EXTERNAL_PATTERNS,\n ...CLI_BUILD_TOOL_EXTERNAL_PATTERNS,\n ],\n onlyBundle: false,\n };\n}\n","import { bundledEntryDepsConfig, libraryBuildDepsConfig, userAppBuildDepsConfig } from \"./deps.js\";\n\nexport {\n isNativeRuntimeDep,\n NATIVE_RUNTIME_DEPS,\n bundledEntryDepsConfig,\n cliBundledEntryDepsConfig,\n libraryBuildDepsConfig,\n userAppBuildDepsConfig,\n} from \"./deps.js\";\n\nexport const baseTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: libraryBuildDepsConfig(),\n};\n\n/** tsdown config for published bundles (cli, keystroke, platform). */\nexport const bundledEntryTsdownConfig = {\n format: [\"esm\", \"cjs\"],\n dts: true,\n clean: true,\n sourcemap: true,\n target: \"node20\",\n deps: bundledEntryDepsConfig(),\n};\n","import { n as keystrokeIgnoreGuardPlugin, t as walkProject } from \"./walk-project-eZ95LOUW.mjs\";\nimport { t as resolveModuleDirs } from \"./resolve-module-dirs-BPHQhRGy.mjs\";\nimport { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { packAssetDirs } from \"@keystrokehq/sandbox/files\";\nimport { baseTsdownConfig, userAppBuildDepsConfig } from \"@keystrokehq/tsdown-config\";\nimport { build, mergeConfig } from \"tsdown\";\nimport { buildStoredRouteManifestForProject } from \"@keystrokehq/manifest\";\n//#region src/resolve-runtime-artifact.ts\nfunction packageRoot(nodeModules, scope, name) {\n\tconst direct = scope ? join(nodeModules, scope, name) : join(nodeModules, name);\n\tif (existsSync(join(direct, \"package.json\"))) return direct;\n\tconst pnpmDir = join(nodeModules, \".pnpm\");\n\tif (!existsSync(pnpmDir)) return null;\n\tfor (const entry of readdirSync(pnpmDir)) {\n\t\tconst candidate = scope ? join(pnpmDir, entry, \"node_modules\", scope, name) : join(pnpmDir, entry, \"node_modules\", name);\n\t\tif (existsSync(join(candidate, \"package.json\"))) return candidate;\n\t}\n\treturn null;\n}\n/** Resolve a file shipped with `@keystrokehq/build` inside the CLI runtime. */\nfunction resolveRuntimeBuildArtifact(runtimeNodeModules, relativePath) {\n\tconst pkgRoot = packageRoot(runtimeNodeModules, \"@keystrokehq\", \"build\");\n\tif (!pkgRoot) throw new Error(\"Keystroke runtime is missing @keystrokehq/build\");\n\tconst artifact = join(pkgRoot, relativePath);\n\tif (!existsSync(artifact)) throw new Error(`Keystroke runtime artifact not found: ${relativePath}`);\n\treturn artifact;\n}\n//#endregion\n//#region src/vitest-plugin.ts\nconst ASSETS_MODULE$1 = \"@keystrokehq/assets\";\nconst virtualPrefix = `\\0${ASSETS_MODULE$1}:`;\n/** Vitest plugin resolving `@keystrokehq/assets` from disk. */\nfunction agentAssetsVitestPlugin(appRoot = process.cwd()) {\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE$1) return null;\n\t\t\treturn `${virtualPrefix}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${virtualPrefix}manifest`) return null;\n\t\t\tmanifest ??= packAssetDirs(appRoot);\n\t\t\treturn `export default ${JSON.stringify(manifest)};`;\n\t\t}\n\t};\n}\nfunction findAppRootFromConfig(configFile) {\n\tif (!configFile) return process.cwd();\n\treturn dirname(configFile);\n}\nfunction agentAssetsVitestPluginFromConfig(configFile) {\n\treturn agentAssetsVitestPlugin(findAppRootFromConfig(configFile));\n}\n//#endregion\n//#region src/resolve-build-filter.ts\n/** Resolve exact build-entry keys for a filtered deploy build. */\nfunction resolveBuildFilter(filter, buildEntries) {\n\tif (filter.length === 0) throw new Error(\"At least one --filter entry is required\");\n\tconst matched = {};\n\tfor (const key of [...new Set(filter)]) {\n\t\tconst entryPath = buildEntries[key];\n\t\tif (!entryPath) throw new Error(`Unknown build entry \"${key}\". Use keys like agents/foo or workflows/bar from walkProject.`);\n\t\tmatched[key] = entryPath;\n\t}\n\treturn matched;\n}\n//#endregion\n//#region src/build-filtered.ts\nfunction toPosix(path) {\n\treturn path.replace(/\\\\/g, \"/\");\n}\nfunction distRelativePath(entryKey) {\n\treturn `${entryKey}.mjs`;\n}\nasync function buildSingleEntry(root, entryKey, entryPath, ignoredFiles) {\n\tmkdirSync(join(root, \".keystroke\"), { recursive: true });\n\tconst scratchRoot = mkdtempSync(join(root, \".keystroke\", \"filter-build-\"));\n\tconst outDir = join(scratchRoot, \"dist\");\n\tconst relativePath = distRelativePath(entryKey);\n\tawait build(mergeConfig(baseTsdownConfig, {\n\t\tentry: { [entryKey]: entryPath },\n\t\tformat: [\"esm\"],\n\t\toutDir,\n\t\tclean: true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t})]\n\t}));\n\treturn {\n\t\tscratchRoot,\n\t\trelativePath\n\t};\n}\nasync function manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap) {\n\tconst moduleFile = toPosix(relative(root, entryPath));\n\tconst distPath = join(root, \"dist\", relativePath);\n\tconst distMapPath = `${distPath}.map`;\n\tconst previousDist = existsSync(distPath) ? readFileSync(distPath) : void 0;\n\tconst hadMap = existsSync(distMapPath);\n\tconst previousMap = hadMap ? readFileSync(distMapPath) : void 0;\n\tmkdirSync(dirname(distPath), { recursive: true });\n\twriteFileSync(distPath, contents);\n\tif (sourceMap) writeFileSync(distMapPath, sourceMap);\n\ttry {\n\t\treturn (await buildStoredRouteManifestForProject(root, { reloadModules: true })).entries.filter((entry) => \"moduleFile\" in entry && entry.moduleFile === moduleFile);\n\t} finally {\n\t\tif (previousDist) writeFileSync(distPath, previousDist);\n\t\telse rmSync(distPath, { force: true });\n\t\tif (previousMap) writeFileSync(distMapPath, previousMap);\n\t\telse if (sourceMap || hadMap) rmSync(distMapPath, { force: true });\n\t}\n}\n/** Build selected modules in isolation for a filtered deploy merge. */\nasync function buildFilteredApp(options) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst phase = options.phase ?? \"deploy\";\n\tconst collectSources = options.collectSources ?? false;\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\tconst matched = resolveBuildFilter(options.filter, walked.buildEntries);\n\tconst files = [];\n\tconst manifestEntries = [];\n\ttry {\n\t\tprocess.chdir(root);\n\t\tfor (const [entryKey, entryPath] of Object.entries(matched)) {\n\t\t\tconst { scratchRoot, relativePath } = await buildSingleEntry(root, entryKey, entryPath, walked.ignoredFiles);\n\t\t\ttry {\n\t\t\t\tconst builtPath = join(scratchRoot, \"dist\", relativePath);\n\t\t\t\tconst mapPath = `${builtPath}.map`;\n\t\t\t\tconst contents = readFileSync(builtPath);\n\t\t\t\tconst sourceMap = existsSync(mapPath) ? readFileSync(mapPath) : void 0;\n\t\t\t\tfiles.push({\n\t\t\t\t\tentryKey,\n\t\t\t\t\trelativePath,\n\t\t\t\t\tcontents,\n\t\t\t\t\tsourceMap\n\t\t\t\t});\n\t\t\t\tmanifestEntries.push(...await manifestEntriesForBuiltModule(root, entryPath, relativePath, contents, sourceMap));\n\t\t\t} finally {\n\t\t\t\trmSync(scratchRoot, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tforce: true\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn {\n\t\tfiles,\n\t\tmanifestEntries,\n\t\tsourceFiles: walked.sourceFiles\n\t};\n}\n//#endregion\n//#region src/index.ts\nconst ASSETS_MODULE = \"@keystrokehq/assets\";\nconst VIRTUAL_PREFIX = `\\0${ASSETS_MODULE}:`;\nfunction renderAssetModule(manifest) {\n\treturn `export default ${JSON.stringify(manifest)};\\n`;\n}\n/** Rolldown plugin: pack src/skills + src/files and expose `@keystrokehq/assets`. */\nfunction agentAssetsPlugin(options) {\n\tconst srcDir = options.srcDir ?? \"src\";\n\tlet manifest = null;\n\treturn {\n\t\tname: \"keystroke-assets\",\n\t\tbuildStart() {\n\t\t\tmanifest = packAssetDirs(options.root, srcDir);\n\t\t},\n\t\tresolveId(source) {\n\t\t\tif (source !== ASSETS_MODULE) return null;\n\t\t\treturn `${VIRTUAL_PREFIX}manifest`;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== `${VIRTUAL_PREFIX}manifest` || !manifest) return null;\n\t\t\treturn renderAssetModule(manifest);\n\t\t},\n\t\tbuildEnd() {\n\t\t\tif (!manifest) return;\n\t\t\tconst outDir = join(options.root, options.outDir ?? \"dist\", \".keystroke\");\n\t\t\tmkdirSync(outDir, { recursive: true });\n\t\t\twriteFileSync(join(outDir, \"assets.mjs\"), renderAssetModule(manifest));\n\t\t}\n\t};\n}\n/** Full tsdown config for user keystroke apps (config + discovered modules only). */\nfunction createAppBuildConfig(options = {}, walked) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst outDir = options.outDir ?? \"dist\";\n\tconst configEntry = existsSync(join(root, \"keystroke.config.ts\")) ? join(root, \"keystroke.config.ts\") : void 0;\n\tconst walkedResult = walked ?? walkProject(root, {\n\t\tsrcDir,\n\t\tphase: options.phase\n\t});\n\tconst discovered = walkedResult.buildEntries;\n\tconst ignoredFiles = walkedResult.ignoredFiles;\n\tconst entries = {\n\t\t...configEntry ? { config: configEntry } : {},\n\t\t...discovered\n\t};\n\tif (Object.keys(entries).length === 0) throw new Error(\"Nothing to build — add keystroke.config.ts or modules under src/\");\n\treturn mergeConfig(baseTsdownConfig, {\n\t\tentry: entries,\n\t\tformat: [\"esm\"],\n\t\toutDir: join(root, outDir),\n\t\tclean: options.clean ?? true,\n\t\tdts: false,\n\t\tloader: { \".md\": \"text\" },\n\t\tdeps: userAppBuildDepsConfig(),\n\t\tplugins: [keystrokeIgnoreGuardPlugin({\n\t\t\troot,\n\t\t\tignoredFiles\n\t\t}), agentAssetsPlugin({\n\t\t\troot,\n\t\t\tsrcDir,\n\t\t\toutDir\n\t\t})]\n\t});\n}\n/** Build user agents, workflows, triggers, and config to `dist/`. */\nasync function buildApp(options = {}) {\n\tconst root = options.root ?? process.cwd();\n\tconst srcDir = options.srcDir ?? \"src\";\n\tconst emitManifest = options.emitManifest ?? true;\n\tconst collectSources = options.collectSources ?? false;\n\tconst phase = options.phase ?? \"build\";\n\tconst previous = process.cwd();\n\tconst walked = walkProject(root, {\n\t\tsrcDir,\n\t\tcollectSources,\n\t\tphase\n\t});\n\ttry {\n\t\tprocess.chdir(root);\n\t\tawait build(createAppBuildConfig({\n\t\t\t...options,\n\t\t\troot\n\t\t}, {\n\t\t\tbuildEntries: walked.buildEntries,\n\t\t\tignoredFiles: walked.ignoredFiles\n\t\t}));\n\t\tif (emitManifest) {\n\t\t\tconst { emitStoredRouteManifestForProject } = await import(\"@keystrokehq/manifest\");\n\t\t\tawait emitStoredRouteManifestForProject(root);\n\t\t}\n\t} finally {\n\t\tprocess.chdir(previous);\n\t}\n\treturn { sourceFiles: walked.sourceFiles };\n}\n/**\n* Watch `src/` and rebuild `dist/` on change.\n*\n* NOT true hot reload — each change runs a full tsdown rebuild. Callers should\n* restart the API server in `onRebuild` so discovery picks up new/changed modules.\n*/\nasync function watchApp(options = {}) {\n\tconst { runWatchApp } = await import(\"./watch-app-DTIeKrbl.mjs\");\n\tawait runWatchApp((watchOptions) => buildApp({\n\t\t...watchOptions,\n\t\temitManifest: false,\n\t\tcollectSources: false\n\t}), options);\n}\n//#endregion\nexport { agentAssetsVitestPlugin, agentAssetsVitestPluginFromConfig, buildApp, buildFilteredApp, createAppBuildConfig, resolveBuildFilter, resolveModuleDirs, resolveRuntimeBuildArtifact, watchApp };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Hn as parseStoredRouteManifest, Ut as ROUTE_MANIFEST_REL_PATH } from "./dist-BnIugffH.mjs";
2
+ import { Gn as parseStoredRouteManifest, Gt as ROUTE_MANIFEST_REL_PATH } from "./dist-CNZVjlhC.mjs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { dirname, join } from "node:path";
5
5
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
@@ -124,4 +124,4 @@ async function mapInParallelBatches(items, batchSize, fn) {
124
124
  //#endregion
125
125
  export { mergeFilteredArtifact as n, packProjectArtifact as r, mapInParallelBatches as t };
126
126
 
127
- //# sourceMappingURL=dist-B4pkCJsM.mjs.map
127
+ //# sourceMappingURL=dist-RRjysgkw.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist-RRjysgkw.mjs","names":[],"sources":["../../../packages/storage/dist/pack-artifact-DVnIKrsg.mjs","../../../packages/storage/dist/index.mjs"],"sourcesContent":["import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport { tmpdir } from \"node:os\";\nimport { ROUTE_MANIFEST_REL_PATH, parseStoredRouteManifest } from \"@keystrokehq/shared\";\n//#region src/pack-dir.ts\n/**\n* Pack a directory tree that contains a `dist/` folder into a gzip tarball\n* suitable for project-server extraction.\n*/\nfunction packDistTree(rootContainingDist) {\n\tconst tempDir = mkdtempSync(join(tmpdir(), \"keystroke-artifact-pack-\"));\n\tconst archivePath = join(tempDir, \"artifact.tgz\");\n\ttry {\n\t\tconst result = spawnSync(\"tar\", [\n\t\t\t\"-czf\",\n\t\t\tarchivePath,\n\t\t\t\"--exclude=._*\",\n\t\t\t\"--exclude=.DS_Store\",\n\t\t\t\"-C\",\n\t\t\trootContainingDist,\n\t\t\t\"dist\"\n\t\t], {\n\t\t\tencoding: \"utf8\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tCOPYFILE_DISABLE: \"1\"\n\t\t\t}\n\t\t});\n\t\tif (result.status !== 0) throw new Error(result.stderr?.trim() || \"Failed to pack project artifact\");\n\t\treturn readFileSync(archivePath);\n\t} finally {\n\t\trmSync(tempDir, {\n\t\t\trecursive: true,\n\t\t\tforce: true\n\t\t});\n\t}\n}\n//#endregion\n//#region src/extract-artifact.ts\n/** Extract a packed project artifact tarball into `destDir` (creates `destDir/dist/`). */\nfunction extractProjectArtifact(archive, destDir) {\n\tconst tempDir = mkdtempSync(join(tmpdir(), \"keystroke-artifact-extract-\"));\n\tconst archivePath = join(tempDir, \"artifact.tgz\");\n\ttry {\n\t\twriteFileSync(archivePath, archive);\n\t\tconst result = spawnSync(\"tar\", [\n\t\t\t\"-xzf\",\n\t\t\tarchivePath,\n\t\t\t\"-C\",\n\t\t\tdestDir\n\t\t], {\n\t\t\tencoding: \"utf8\",\n\t\t\tenv: {\n\t\t\t\t...process.env,\n\t\t\t\tCOPYFILE_DISABLE: \"1\"\n\t\t\t}\n\t\t});\n\t\tif (result.status !== 0) throw new Error(result.stderr?.trim() || \"Failed to extract project artifact\");\n\t} finally {\n\t\trmSync(tempDir, {\n\t\t\trecursive: true,\n\t\t\tforce: true\n\t\t});\n\t}\n}\n//#endregion\n//#region src/merge-route-manifest.ts\nfunction moduleFileOf(entry) {\n\treturn \"moduleFile\" in entry && typeof entry.moduleFile === \"string\" ? entry.moduleFile : void 0;\n}\n/** Replace manifest rows for rebuilt modules while keeping untouched routes and metadata. */\nfunction mergeStoredRouteManifest(base, rebuiltEntries) {\n\tconst rebuiltModuleFiles = new Set(rebuiltEntries.map(moduleFileOf).filter((value) => Boolean(value)));\n\tconst keptEntries = base.entries.filter((entry) => {\n\t\tconst moduleFile = moduleFileOf(entry);\n\t\tif (!moduleFile) return true;\n\t\treturn !rebuiltModuleFiles.has(moduleFile);\n\t});\n\tconst filteredRebuilt = rebuiltEntries.filter((entry) => entry.kind !== \"health\");\n\treturn {\n\t\t...base,\n\t\tentries: [...keptEntries, ...filteredRebuilt]\n\t};\n}\n//#endregion\n//#region src/merge-filtered-artifact.ts\nasync function mergeFilteredArtifact(input) {\n\tconst mergeRoot = mkdtempSync(join(tmpdir(), \"keystroke-artifact-merge-\"));\n\ttry {\n\t\textractProjectArtifact(input.baseArchive, mergeRoot);\n\t\tconst manifestPath = join(mergeRoot, ROUTE_MANIFEST_REL_PATH);\n\t\tconst mergedManifest = mergeStoredRouteManifest(parseStoredRouteManifest(JSON.parse(readFileSync(manifestPath, \"utf8\"))), input.filtered.manifestEntries);\n\t\twriteFileSync(manifestPath, `${JSON.stringify(mergedManifest, null, 2)}\\n`);\n\t\tfor (const file of input.filtered.files) {\n\t\t\tconst destination = join(mergeRoot, \"dist\", file.relativePath);\n\t\t\tmkdirSync(dirname(destination), { recursive: true });\n\t\t\twriteFileSync(destination, file.contents);\n\t\t\tif (file.sourceMap) writeFileSync(`${destination}.map`, file.sourceMap);\n\t\t}\n\t\treturn packDistTree(mergeRoot);\n\t} finally {\n\t\trmSync(mergeRoot, {\n\t\t\trecursive: true,\n\t\t\tforce: true\n\t\t});\n\t}\n}\n//#endregion\n//#region src/pack-artifact.ts\n/** Pack `dist/` into a gzip tarball suitable for `/app` extraction in the project server image. */\nfunction packProjectArtifact(projectRoot) {\n\tif (!existsSync(join(projectRoot, \"dist\"))) throw new Error(\"dist/ not found — run keystroke build first\");\n\treturn packDistTree(projectRoot);\n}\n//#endregion\nexport { packDistTree as a, extractProjectArtifact as i, mergeFilteredArtifact as n, mergeStoredRouteManifest as r, packProjectArtifact as t };\n\n//# sourceMappingURL=pack-artifact-DVnIKrsg.mjs.map","import { a as packDistTree, i as extractProjectArtifact, n as mergeFilteredArtifact, r as mergeStoredRouteManifest, t as packProjectArtifact } from \"./pack-artifact-DVnIKrsg.mjs\";\nimport { CreateBucketCommand, DeleteBucketCommand, DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutBucketAclCommand, PutBucketPolicyCommand, PutObjectCommand, S3Client } from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport { spawnSync } from \"node:child_process\";\nimport { tmpdir } from \"node:os\";\nimport { ROUTE_MANIFEST_REL_PATH } from \"@keystrokehq/shared\";\nimport { createHash } from \"node:crypto\";\n//#region src/config.ts\nfunction readEnv$1(env, ...keys) {\n\tfor (const key of keys) {\n\t\tconst value = env[key]?.trim();\n\t\tif (value) return value;\n\t}\n}\nfunction requireEnv(env, keys) {\n\tconst candidates = Array.isArray(keys) ? keys : [keys];\n\tconst value = readEnv$1(env, ...candidates);\n\tif (!value) throw new Error(`${candidates[0]} is required`);\n\treturn value;\n}\n/** Admin S3 credentials for storage plugins (bucket is per-org, not from env). */\nfunction storageAdminConfigFromEnv(env = process.env) {\n\tconst accessKeyId = requireEnv(env, [\"STORAGE_ACCESS_KEY_ID\", \"AWS_ACCESS_KEY_ID\"]);\n\tconst secretAccessKey = requireEnv(env, [\"STORAGE_SECRET_ACCESS_KEY\", \"AWS_SECRET_ACCESS_KEY\"]);\n\tconst endpoint = requireEnv(env, [\n\t\t\"STORAGE_ENDPOINT\",\n\t\t\"AWS_ENDPOINT_URL_S3\",\n\t\t\"AWS_S3_ENDPOINT\"\n\t]);\n\treturn {\n\t\tregion: readEnv$1(env, \"STORAGE_REGION\", \"AWS_REGION\") ?? \"us-east-1\",\n\t\taccessKeyId,\n\t\tsecretAccessKey,\n\t\tendpoint,\n\t\tforcePathStyle: env.STORAGE_FORCE_PATH_STYLE === void 0 ? true : env.STORAGE_FORCE_PATH_STYLE === \"true\"\n\t};\n}\n/** Full client config including bucket — for integration tests and explicit bucket callers. */\nfunction storageConfigFromEnv(env = process.env) {\n\tconst bucket = requireEnv(env, [\"STORAGE_BUCKET\", \"BUCKET_NAME\"]);\n\treturn {\n\t\t...storageAdminConfigFromEnv(env),\n\t\tbucket\n\t};\n}\n/** Endpoint for presigned URLs fetched inside project-server containers (e.g. `http://minio:9000`). */\nfunction containerPresignEndpointFromEnv(hostEndpoint, env = process.env) {\n\tconst override = readEnv$1(env, \"STORAGE_CONTAINER_ENDPOINT\");\n\tif (override) return override;\n\ttry {\n\t\tconst url = new URL(hostEndpoint);\n\t\tif (url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\") {\n\t\t\tconst port = url.port || (url.protocol === \"https:\" ? \"443\" : \"9000\");\n\t\t\treturn `${url.protocol}//minio:${port}`;\n\t\t}\n\t} catch {}\n\treturn hostEndpoint;\n}\n//#endregion\n//#region src/keys.ts\n/** Object key for a built project artifact tarball. */\nfunction projectArtifactKey(projectId, version) {\n\treturn `projects/${projectId}/artifacts/${version}.tgz`;\n}\n/**\n* Per-artifact source manifest (the deploy's file tree: path -> id + content\n* hash, plus resource refs). One per deploy.\n*/\nfunction projectSourceManifestKey(projectId, artifactId) {\n\treturn `projects/${projectId}/sources/${artifactId}/index.json`;\n}\nconst SHA256_HEX = /^[a-f0-9]{64}$/;\n/** True when `hash` is a lowercase hex sha256 digest (64 chars). */\nfunction isSourceBlobHash(hash) {\n\treturn SHA256_HEX.test(hash);\n}\n/**\n* Content-addressed key for a single source file's contents, deduped across all\n* of a project's deploys. `hash` is a lowercase hex sha256 of the file bytes.\n*/\nfunction projectSourceBlobKey(projectId, hash) {\n\tif (!isSourceBlobHash(hash)) throw new Error(\"Invalid source blob hash\");\n\treturn `projects/${projectId}/sources/blobs/${hash}`;\n}\nconst AVATAR_EXTENSION = /^[a-z0-9]+$/;\n/** Object key for a chat attachment in org-private storage. */\nfunction chatAttachmentStorageKey(projectId, id, ext) {\n\tconst normalizedExt = ext.replace(/^\\./, \"\").toLowerCase();\n\tif (!AVATAR_EXTENSION.test(normalizedExt)) throw new Error(\"Invalid chat attachment extension\");\n\treturn `chat-attachments/${projectId}/${id}.${normalizedExt}`;\n}\n/** True when `key` is a chat attachment owned by `projectId`. */\nfunction isChatAttachmentStorageKey(key, projectId) {\n\tconst prefix = `chat-attachments/${projectId}/`;\n\tif (!key.startsWith(prefix)) return false;\n\tconst remainder = key.slice(prefix.length);\n\treturn remainder.length > 0 && !remainder.includes(\"/\");\n}\n/** Object key for a user's custom profile avatar in the shared keystroke-users bucket. */\nfunction userAvatarStorageKey(userId, extension) {\n\tconst ext = extension.replace(/^\\./, \"\").toLowerCase();\n\tif (!AVATAR_EXTENSION.test(ext)) throw new Error(\"Invalid avatar extension\");\n\treturn `avatars/${userId}/avatar.${ext}`;\n}\n/** True when `key` is the canonical avatar object for `userId`. */\nfunction isUserAvatarStorageKey(key, userId) {\n\tconst prefix = `avatars/${userId}/avatar.`;\n\tif (!key.startsWith(prefix)) return false;\n\tconst ext = key.slice(prefix.length);\n\treturn AVATAR_EXTENSION.test(ext);\n}\n/** Object key for an org logo in the shared keystroke-assets bucket. */\nfunction orgLogoStorageKey(organizationId, variant, extension) {\n\tconst ext = extension.replace(/^\\./, \"\").toLowerCase();\n\tif (!AVATAR_EXTENSION.test(ext)) throw new Error(\"Invalid org logo extension\");\n\treturn `org-logos/${organizationId}/logo-${variant}.${ext}`;\n}\n/** True when `key` is the canonical logo object for `organizationId` and `variant`. */\nfunction isOrgLogoStorageKey(key, organizationId, variant) {\n\tconst prefix = `org-logos/${organizationId}/logo-${variant}.`;\n\tif (!key.startsWith(prefix)) return false;\n\tconst ext = key.slice(prefix.length);\n\treturn AVATAR_EXTENSION.test(ext);\n}\n//#endregion\n//#region src/map-in-batches.ts\n/** Default concurrency for parallel blob downloads and file writes. */\nconst DEFAULT_PARALLEL_BATCH_SIZE = 8;\n/** Run `fn` over `items` in parallel batches of `batchSize`. */\nasync function mapInParallelBatches(items, batchSize, fn) {\n\tif (batchSize < 1) throw new Error(\"batchSize must be at least 1\");\n\tconst results = [];\n\tfor (let index = 0; index < items.length; index += batchSize) {\n\t\tconst batch = items.slice(index, index + batchSize);\n\t\tresults.push(...await Promise.all(batch.map(fn)));\n\t}\n\treturn results;\n}\n//#endregion\n//#region src/load-project-source-files.ts\n/** Matches deploy-time source snapshot limits in @keystrokehq/build walk-project. */\nconst MAX_ACTIVE_SOURCE_DOWNLOAD_BYTES = 8 * 1024 * 1024;\nasync function loadProjectSourceFiles(storage, projectId, manifest, options = {}) {\n\tconst maxTotalBytes = options.maxTotalBytes ?? 8388608;\n\tconst files = [];\n\tlet totalBytes = 0;\n\tfor (let index = 0; index < manifest.files.length; index += 8) {\n\t\tconst batch = manifest.files.slice(index, index + 8);\n\t\tconst batchResults = await Promise.all(batch.map(async (file) => {\n\t\t\tconst bytes = await storage.getObject(projectSourceBlobKey(projectId, file.hash));\n\t\t\tconst contents = new TextDecoder().decode(bytes);\n\t\t\treturn {\n\t\t\t\tpath: file.path,\n\t\t\t\tcontents,\n\t\t\t\tbyteLength: Buffer.byteLength(contents, \"utf8\")\n\t\t\t};\n\t\t}));\n\t\tfor (const result of batchResults) {\n\t\t\ttotalBytes += result.byteLength;\n\t\t\tif (totalBytes > maxTotalBytes) throw new Error(\"Active source snapshot exceeds download size limit\");\n\t\t\tfiles.push({\n\t\t\t\tpath: result.path,\n\t\t\t\tcontents: result.contents\n\t\t\t});\n\t\t}\n\t}\n\treturn files;\n}\n//#endregion\n//#region src/create-storage.ts\nconst DEFAULT_PRESIGN_TTL_SECONDS = 900;\nfunction createStorage(config) {\n\tconst client = new S3Client(toClientConfig(config));\n\treturn {\n\t\tasync putObject(input) {\n\t\t\tawait client.send(new PutObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: input.key,\n\t\t\t\tBody: input.body,\n\t\t\t\tContentType: input.contentType\n\t\t\t}));\n\t\t},\n\t\tasync getObject(key) {\n\t\t\tconst response = await client.send(new GetObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: key\n\t\t\t}));\n\t\t\tif (!response.Body) throw new Error(`Object body missing for key ${key}`);\n\t\t\treturn response.Body.transformToByteArray();\n\t\t},\n\t\tasync headObject(key) {\n\t\t\ttry {\n\t\t\t\treturn { contentLength: (await client.send(new HeadObjectCommand({\n\t\t\t\t\tBucket: config.bucket,\n\t\t\t\t\tKey: key\n\t\t\t\t}))).ContentLength ?? 0 };\n\t\t\t} catch (error) {\n\t\t\t\tif (isNotFoundError(error)) return;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\tasync presignGet(input) {\n\t\t\treturn getSignedUrl(client, new GetObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: input.key\n\t\t\t}), { expiresIn: input.expiresInSeconds ?? DEFAULT_PRESIGN_TTL_SECONDS });\n\t\t},\n\t\tasync presignPut(input) {\n\t\t\treturn getSignedUrl(client, new PutObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: input.key,\n\t\t\t\tContentType: input.contentType ?? \"application/gzip\"\n\t\t\t}), { expiresIn: input.expiresInSeconds ?? DEFAULT_PRESIGN_TTL_SECONDS });\n\t\t},\n\t\tasync deleteObject(key) {\n\t\t\tawait client.send(new DeleteObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: key\n\t\t\t}));\n\t\t},\n\t\tasync listObjects(prefix) {\n\t\t\tconst keys = [];\n\t\t\tlet continuationToken;\n\t\t\tdo {\n\t\t\t\tconst response = await client.send(new ListObjectsV2Command({\n\t\t\t\t\tBucket: config.bucket,\n\t\t\t\t\tPrefix: prefix,\n\t\t\t\t\tContinuationToken: continuationToken\n\t\t\t\t}));\n\t\t\t\tfor (const object of response.Contents ?? []) if (object.Key) keys.push(object.Key);\n\t\t\t\tcontinuationToken = response.IsTruncated ? response.NextContinuationToken : void 0;\n\t\t\t} while (continuationToken);\n\t\t\treturn keys;\n\t\t}\n\t};\n}\n/** Presign URLs for project-server containers using `STORAGE_CONTAINER_ENDPOINT` when set. */\nfunction createContainerPresignStorage(config, env = process.env) {\n\treturn createStorage({\n\t\t...config,\n\t\tendpoint: containerPresignEndpointFromEnv(config.endpoint, env)\n\t});\n}\nfunction toClientConfig(config) {\n\treturn {\n\t\tregion: config.region,\n\t\tcredentials: {\n\t\t\taccessKeyId: config.accessKeyId,\n\t\t\tsecretAccessKey: config.secretAccessKey\n\t\t},\n\t\tendpoint: config.endpoint,\n\t\tforcePathStyle: config.forcePathStyle\n\t};\n}\nfunction isNotFoundError(error) {\n\tif (!error || typeof error !== \"object\") return false;\n\tconst name = \"name\" in error ? String(error.name) : \"\";\n\tconst status = \"$metadata\" in error ? error.$metadata : void 0;\n\treturn name === \"NotFound\" || name === \"NoSuchKey\" || status?.httpStatusCode === 404;\n}\n//#endregion\n//#region src/extract-route-manifest.ts\nvar RouteManifestNotFoundError = class extends Error {\n\tconstructor(message = `Route manifest missing in artifact (${ROUTE_MANIFEST_REL_PATH})`) {\n\t\tsuper(message);\n\t\tthis.name = \"RouteManifestNotFoundError\";\n\t}\n};\n/** Read `.keystroke/route-manifest.json` from a packed project artifact tarball. */\nfunction extractRouteManifestFromArtifact(archive) {\n\tconst tempDir = mkdtempSync(join(tmpdir(), \"keystroke-artifact-\"));\n\tconst archivePath = join(tempDir, \"artifact.tgz\");\n\ttry {\n\t\twriteFileSync(archivePath, archive);\n\t\tif (spawnSync(\"tar\", [\n\t\t\t\"-xzf\",\n\t\t\tarchivePath,\n\t\t\t\"-C\",\n\t\t\ttempDir,\n\t\t\tROUTE_MANIFEST_REL_PATH\n\t\t], { encoding: \"utf8\" }).status !== 0) throw new RouteManifestNotFoundError();\n\t\tconst raw = readFileSync(join(tempDir, ROUTE_MANIFEST_REL_PATH), \"utf8\");\n\t\treturn JSON.parse(raw);\n\t} catch (error) {\n\t\tif (error instanceof RouteManifestNotFoundError) throw error;\n\t\tthrow new RouteManifestNotFoundError(error instanceof Error ? error.message : \"Failed to extract route manifest\");\n\t} finally {\n\t\trmSync(tempDir, {\n\t\t\trecursive: true,\n\t\t\tforce: true\n\t\t});\n\t}\n}\n//#endregion\n//#region src/s3-errors.ts\nfunction isBucketAlreadyExistsError(error) {\n\tif (!error || typeof error !== \"object\") return false;\n\tconst name = \"name\" in error ? String(error.name) : \"\";\n\tconst code = \"Code\" in error ? String(error.Code) : \"\";\n\treturn name === \"BucketAlreadyOwnedByYou\" || code === \"BucketAlreadyOwnedByYou\" || name === \"BucketAlreadyExists\" || code === \"BucketAlreadyExists\";\n}\nfunction isStorageNotFoundError(error) {\n\tif (!error || typeof error !== \"object\") return false;\n\tconst record = error;\n\tconst name = typeof record.name === \"string\" ? record.name : \"\";\n\tconst code = typeof record.Code === \"string\" ? record.Code : \"\";\n\tconst status = typeof record.$metadata === \"object\" && record.$metadata !== null ? record.$metadata.httpStatusCode : void 0;\n\treturn name === \"NoSuchKey\" || code === \"NoSuchKey\" || code === \"NotFound\" || status === 404;\n}\nfunction isStorageBucketNotFoundError(error) {\n\tif (!error || typeof error !== \"object\") return false;\n\tconst record = error;\n\tconst name = typeof record.name === \"string\" ? record.name : \"\";\n\tconst code = typeof record.Code === \"string\" ? record.Code : \"\";\n\tconst status = typeof record.$metadata === \"object\" && record.$metadata !== null ? record.$metadata.httpStatusCode : void 0;\n\treturn name === \"NoSuchBucket\" || code === \"NoSuchBucket\" || name === \"NotFound\" || status === 404;\n}\n//#endregion\n//#region src/asset-storage.ts\n/** Shared bucket for cross-org public assets (avatars, org sidebar logos). */\nconst KEYSTROKE_ASSETS_BUCKET = \"keystroke-assets\";\n/** Env var for the browser-facing origin of public asset objects (no trailing slash). */\nconst KEYSTROKE_ASSETS_PUBLIC_URL_BASE_ENV = \"KEYSTROKE_ASSETS_PUBLIC_URL_BASE\";\nconst KEYSTROKE_ASSETS_AVATAR_PREFIX = \"avatars/\";\nconst KEYSTROKE_ASSETS_ORG_LOGO_PREFIX = \"org-logos/\";\nfunction readEnv(env, key) {\n\treturn env[key]?.trim() || void 0;\n}\n/** Default path-style base when `KEYSTROKE_ASSETS_PUBLIC_URL_BASE` is unset (local MinIO). */\nfunction defaultKeystrokeAssetsPublicUrlBase(env = process.env) {\n\treturn `${storageAdminConfigFromEnv(env).endpoint.replace(/\\/+$/, \"\")}/${KEYSTROKE_ASSETS_BUCKET}`;\n}\n/** Public URL prefix for asset objects — configured base or local path-style default. */\nfunction keystrokeAssetsPublicUrlBase(env = process.env) {\n\tconst configured = readEnv(env, KEYSTROKE_ASSETS_PUBLIC_URL_BASE_ENV);\n\tif (configured) return configured.replace(/\\/+$/, \"\");\n\treturn defaultKeystrokeAssetsPublicUrlBase(env);\n}\nfunction keystrokeAssetsPublicUrlPrefixes(env = process.env) {\n\tconst prefixes = [keystrokeAssetsPublicUrlBase(env)];\n\tif (readEnv(env, \"KEYSTROKE_ASSETS_PUBLIC_URL_BASE\")) prefixes.push(defaultKeystrokeAssetsPublicUrlBase(env));\n\treturn [...new Set(prefixes)];\n}\nfunction createAssetsStorageClient(env = process.env) {\n\treturn createStorage({\n\t\t...storageAdminConfigFromEnv(env),\n\t\tbucket: KEYSTROKE_ASSETS_BUCKET\n\t});\n}\n/** Stable public URL for an object in the keystroke-assets bucket. */\nfunction publicKeystrokeAssetsObjectUrl(key, env = process.env) {\n\treturn `${keystrokeAssetsPublicUrlBase(env)}/${key}`;\n}\n/** Extract the object key from a public keystroke-assets URL when it matches `requiredPrefix`. */\nfunction keystrokeAssetsKeyFromPublicUrl(url, requiredPrefix, env = process.env) {\n\tfor (const prefix of keystrokeAssetsPublicUrlPrefixes(env)) {\n\t\tconst normalizedPrefix = `${prefix.replace(/\\/+$/, \"\")}/`;\n\t\tif (!url.startsWith(normalizedPrefix)) continue;\n\t\tconst key = decodeURIComponent(url.slice(normalizedPrefix.length).split(\"?\")[0] ?? \"\");\n\t\tif (key.startsWith(requiredPrefix)) return key;\n\t}\n\treturn null;\n}\nfunction isKeystrokeAssetsAvatarPublicUrl(url, env = process.env) {\n\treturn keystrokeAssetsKeyFromPublicUrl(url, KEYSTROKE_ASSETS_AVATAR_PREFIX, env) !== null;\n}\nfunction keystrokeAssetsAvatarKeyFromPublicUrl(url, env = process.env) {\n\treturn keystrokeAssetsKeyFromPublicUrl(url, KEYSTROKE_ASSETS_AVATAR_PREFIX, env);\n}\nfunction isKeystrokeAssetsOrgLogoPublicUrl(url, env = process.env) {\n\treturn keystrokeAssetsKeyFromPublicUrl(url, KEYSTROKE_ASSETS_ORG_LOGO_PREFIX, env) !== null;\n}\nfunction keystrokeAssetsOrgLogoKeyFromPublicUrl(url, env = process.env) {\n\treturn keystrokeAssetsKeyFromPublicUrl(url, KEYSTROKE_ASSETS_ORG_LOGO_PREFIX, env);\n}\nasync function ensureKeystrokeAssetsBucket(env = process.env) {\n\tconst adminConfig = storageAdminConfigFromEnv(env);\n\tconst adminClient = new S3Client({\n\t\tregion: adminConfig.region,\n\t\tcredentials: {\n\t\t\taccessKeyId: adminConfig.accessKeyId,\n\t\t\tsecretAccessKey: adminConfig.secretAccessKey\n\t\t},\n\t\tendpoint: adminConfig.endpoint,\n\t\tforcePathStyle: adminConfig.forcePathStyle\n\t});\n\tawait createAssetsBucketIfNeeded(adminClient, KEYSTROKE_ASSETS_BUCKET);\n\tawait applyPublicAssetsBucketAcl(adminClient, KEYSTROKE_ASSETS_BUCKET);\n\tawait applyPublicAssetsBucketPolicy(adminClient, KEYSTROKE_ASSETS_BUCKET);\n}\nasync function createAssetsBucketIfNeeded(adminClient, bucket) {\n\ttry {\n\t\tawait adminClient.send(new CreateBucketCommand({\n\t\t\tBucket: bucket,\n\t\t\tACL: \"public-read\"\n\t\t}));\n\t\treturn;\n\t} catch (error) {\n\t\tif (isBucketAlreadyExistsError(error)) return;\n\t}\n\ttry {\n\t\tawait adminClient.send(new CreateBucketCommand({ Bucket: bucket }));\n\t} catch (error) {\n\t\tif (!isBucketAlreadyExistsError(error)) throw error;\n\t}\n}\nasync function applyPublicAssetsBucketAcl(adminClient, bucket) {\n\ttry {\n\t\tawait adminClient.send(new PutBucketAclCommand({\n\t\t\tBucket: bucket,\n\t\t\tACL: \"public-read\"\n\t\t}));\n\t} catch (error) {\n\t\tif (!isUnsupportedStorageFeatureError(error)) console.warn(\"[storage] PutBucketAcl failed (continuing):\", error);\n\t}\n}\nasync function applyPublicAssetsBucketPolicy(adminClient, bucket) {\n\ttry {\n\t\tawait adminClient.send(new PutBucketPolicyCommand({\n\t\t\tBucket: bucket,\n\t\t\tPolicy: JSON.stringify({\n\t\t\t\tVersion: \"2012-10-17\",\n\t\t\t\tStatement: [{\n\t\t\t\t\tEffect: \"Allow\",\n\t\t\t\t\tPrincipal: \"*\",\n\t\t\t\t\tAction: [\"s3:GetObject\"],\n\t\t\t\t\tResource: [`arn:aws:s3:::${bucket}/${KEYSTROKE_ASSETS_AVATAR_PREFIX}*`, `arn:aws:s3:::${bucket}/${KEYSTROKE_ASSETS_ORG_LOGO_PREFIX}*`]\n\t\t\t\t}]\n\t\t\t})\n\t\t}));\n\t} catch (error) {\n\t\tif (!isUnsupportedStorageFeatureError(error)) console.warn(\"[storage] PutBucketPolicy failed (continuing):\", error);\n\t}\n}\nfunction isUnsupportedStorageFeatureError(error) {\n\tif (!error || typeof error !== \"object\") return false;\n\tconst name = \"name\" in error ? String(error.name) : \"\";\n\tconst code = \"Code\" in error ? String(error.Code) : \"\";\n\treturn name === \"NotImplemented\" || code === \"NotImplemented\" || code === \"NotSupported\";\n}\n//#endregion\n//#region src/provision/names.ts\nconst DEFAULT_BUCKET_NAME_PREFIX = \"ks\";\nconst S3_BUCKET_NAME_MAX = 63;\n/** Deterministic bucket segment; keeps short test ids readable, hashes UUID-length ids. */\nfunction bucketIdSegment(id, hashLength = 10) {\n\tif (id.length <= 24 && !/^[0-9a-f]{8}-[0-9a-f]{4}-/i.test(id)) return id;\n\treturn createHash(\"sha256\").update(id).digest(\"hex\").slice(0, hashLength);\n}\nfunction assertBucketName(name) {\n\tif (name.length > S3_BUCKET_NAME_MAX) throw new Error(`bucket name exceeds ${S3_BUCKET_NAME_MAX} chars (${name.length}): ${name}`);\n\treturn name;\n}\nfunction orgStorageBucketName(input, prefix = DEFAULT_BUCKET_NAME_PREFIX) {\n\treturn assertBucketName(`${prefix.trim().replace(/-+$/g, \"\")}-${input.organizationId.toLowerCase()}`);\n}\nfunction orgAgentBucketName(input) {\n\tconst orgBucket = input.orgBucket ?? (input.organizationId ? orgStorageBucketName({ organizationId: input.organizationId }) : void 0);\n\tif (!orgBucket) throw new Error(\"orgAgentBucketName requires organizationId or orgBucket\");\n\treturn assertBucketName(`${orgBucket}-${bucketIdSegment(input.agentId)}`);\n}\n//#endregion\n//#region src/workspace/sync.ts\nconst DEFAULT_UPLOAD_CONCURRENCY = 8;\nfunction walkFiles(root) {\n\tconst files = [];\n\tconst stack = [root];\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tfor (const entry of readdirSync(current, { withFileTypes: true })) {\n\t\t\tconst full = join(current, entry.name);\n\t\t\tif (entry.isDirectory()) stack.push(full);\n\t\t\telse if (entry.isFile()) files.push(full);\n\t\t}\n\t}\n\treturn files;\n}\nfunction collectWorkspaceObjects(workspaceRoot) {\n\treturn walkFiles(workspaceRoot).map((file) => ({\n\t\tkey: relative(workspaceRoot, file).split(\"\\\\\").join(\"/\"),\n\t\tbody: readFileSync(file)\n\t}));\n}\n/** Keys present in object storage but absent from the local workspace root. */\nfunction workspaceKeysToDelete(remoteKeys, localKeys) {\n\treturn remoteKeys.filter((key) => !localKeys.has(key));\n}\nfunction s3Client(config) {\n\treturn new S3Client({\n\t\tregion: config.region,\n\t\tendpoint: config.endpoint,\n\t\tforcePathStyle: config.forcePathStyle,\n\t\tcredentials: {\n\t\t\taccessKeyId: config.accessKeyId,\n\t\t\tsecretAccessKey: config.secretAccessKey\n\t\t}\n\t});\n}\n/** Create the bucket named in `config` when missing (idempotent for races). */\nasync function ensureStorageBucket(config) {\n\tconst client = s3Client(config);\n\ttry {\n\t\tawait client.send(new CreateBucketCommand({ Bucket: config.bucket }));\n\t} catch (error) {\n\t\tif (!isBucketAlreadyExistsError(error)) throw error;\n\t}\n}\nasync function uploadWorkspaceObjects(config, objects, concurrency = DEFAULT_UPLOAD_CONCURRENCY) {\n\tif (objects.length === 0) return;\n\tconst client = s3Client(config);\n\tlet index = 0;\n\tasync function worker() {\n\t\twhile (index < objects.length) {\n\t\t\tconst current = objects[index++];\n\t\t\tawait client.send(new PutObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: current.key,\n\t\t\t\tBody: current.body\n\t\t\t}));\n\t\t}\n\t}\n\tconst workers = Array.from({ length: Math.min(concurrency, objects.length) }, () => worker());\n\tawait Promise.all(workers);\n}\nasync function deleteWorkspaceObjects(config, keys, concurrency = DEFAULT_UPLOAD_CONCURRENCY) {\n\tif (keys.length === 0) return;\n\tconst client = s3Client(config);\n\tlet index = 0;\n\tasync function worker() {\n\t\twhile (index < keys.length) {\n\t\t\tconst key = keys[index++];\n\t\t\tawait client.send(new DeleteObjectCommand({\n\t\t\t\tBucket: config.bucket,\n\t\t\t\tKey: key\n\t\t\t}));\n\t\t}\n\t}\n\tconst workers = Array.from({ length: Math.min(concurrency, keys.length) }, () => worker());\n\tawait Promise.all(workers);\n}\n/** Mirror the host agent workspace directory to the per-agent bucket (upsert + delete stale keys). */\nasync function syncAgentWorkspaceToBucket(input) {\n\tconst bucket = orgAgentBucketName({\n\t\torgBucket: input.orgBucket,\n\t\tagentId: input.agentId\n\t});\n\tconst config = {\n\t\t...input.admin,\n\t\tbucket\n\t};\n\tawait ensureStorageBucket(config);\n\tconst objects = collectWorkspaceObjects(input.agentRoot);\n\tconst localKeys = new Set(objects.map((object) => object.key));\n\tawait deleteWorkspaceObjects(config, workspaceKeysToDelete(await createStorage(config).listObjects(\"\"), localKeys));\n\tawait uploadWorkspaceObjects(config, objects);\n}\n//#endregion\n//#region src/provision/minio.ts\nfunction minioStoragePlugin(options = {}) {\n\tconst adminConfig = storageAdminConfigFromEnv(options.env ?? process.env);\n\tconst adminClient = new S3Client({\n\t\tregion: adminConfig.region,\n\t\tcredentials: {\n\t\t\taccessKeyId: adminConfig.accessKeyId,\n\t\t\tsecretAccessKey: adminConfig.secretAccessKey\n\t\t},\n\t\tendpoint: adminConfig.endpoint,\n\t\tforcePathStyle: adminConfig.forcePathStyle\n\t});\n\treturn {\n\t\tasync provisionOrganization(input) {\n\t\t\tconst bucket = orgStorageBucketName(input, options.bucketNamePrefix);\n\t\t\ttry {\n\t\t\t\tawait adminClient.send(new CreateBucketCommand({ Bucket: bucket }));\n\t\t\t} catch (error) {\n\t\t\t\tif (!isBucketAlreadyExistsError(error)) throw error;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tbucket,\n\t\t\t\tendpoint: adminConfig.endpoint,\n\t\t\t\taccessKeyId: adminConfig.accessKeyId,\n\t\t\t\tsecretAccessKey: adminConfig.secretAccessKey,\n\t\t\t\tregion: adminConfig.region,\n\t\t\t\tforcePathStyle: adminConfig.forcePathStyle\n\t\t\t};\n\t\t},\n\t\tasync deprovisionOrganization(result) {\n\t\t\tconst client = new S3Client({\n\t\t\t\tregion: result.region ?? adminConfig.region,\n\t\t\t\tcredentials: {\n\t\t\t\t\taccessKeyId: result.accessKeyId,\n\t\t\t\t\tsecretAccessKey: result.secretAccessKey\n\t\t\t\t},\n\t\t\t\tendpoint: result.endpoint,\n\t\t\t\tforcePathStyle: result.forcePathStyle ?? true\n\t\t\t});\n\t\t\tif (((await client.send(new ListObjectsV2Command({\n\t\t\t\tBucket: result.bucket,\n\t\t\t\tMaxKeys: 1\n\t\t\t}))).KeyCount ?? 0) > 0) throw new Error(`Refusing to delete non-empty storage bucket ${result.bucket}`);\n\t\t\tawait client.send(new DeleteBucketCommand({ Bucket: result.bucket }));\n\t\t}\n\t};\n}\n//#endregion\nexport { DEFAULT_PARALLEL_BATCH_SIZE, KEYSTROKE_ASSETS_AVATAR_PREFIX, KEYSTROKE_ASSETS_BUCKET, KEYSTROKE_ASSETS_ORG_LOGO_PREFIX, KEYSTROKE_ASSETS_PUBLIC_URL_BASE_ENV, MAX_ACTIVE_SOURCE_DOWNLOAD_BYTES, RouteManifestNotFoundError, bucketIdSegment, chatAttachmentStorageKey, collectWorkspaceObjects, containerPresignEndpointFromEnv, createAssetsStorageClient, createContainerPresignStorage, createStorage, defaultKeystrokeAssetsPublicUrlBase, deleteWorkspaceObjects, ensureKeystrokeAssetsBucket, ensureStorageBucket, extractProjectArtifact, extractRouteManifestFromArtifact, isBucketAlreadyExistsError, isChatAttachmentStorageKey, isKeystrokeAssetsAvatarPublicUrl, isKeystrokeAssetsOrgLogoPublicUrl, isOrgLogoStorageKey, isSourceBlobHash, isStorageBucketNotFoundError, isStorageNotFoundError, isUserAvatarStorageKey, keystrokeAssetsAvatarKeyFromPublicUrl, keystrokeAssetsKeyFromPublicUrl, keystrokeAssetsOrgLogoKeyFromPublicUrl, keystrokeAssetsPublicUrlBase, loadProjectSourceFiles, mapInParallelBatches, mergeFilteredArtifact, mergeStoredRouteManifest, minioStoragePlugin, orgAgentBucketName, orgLogoStorageKey, orgStorageBucketName, packDistTree, packProjectArtifact, projectArtifactKey, projectSourceBlobKey, projectSourceManifestKey, publicKeystrokeAssetsObjectUrl, storageAdminConfigFromEnv, storageConfigFromEnv, syncAgentWorkspaceToBucket, uploadWorkspaceObjects, userAvatarStorageKey, workspaceKeysToDelete };\n\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { m as emitStoredRouteManifestForProject } from "./dist-BW3AMCud.mjs";
2
+ import { m as emitStoredRouteManifestForProject } from "./dist-BaOUOcKY.mjs";
3
3
  export { emitStoredRouteManifestForProject };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { $ as HistoryRunCancelResponseSchema, $t as StartOAuthConnectionResultSchema, A as CreateCustomAppRequestSchema, An as WorkspaceTriggerListResponseSchema, At as PresignProjectSourceRequestSchema, B as CredentialConsumerListQuerySchema, Bn as parseAppSlug, Bt as PromptResponseSchema, C as ConnectAuthorizeUrlResponseSchema, Cn as WorkflowRunDetailResponseSchema, Ct as OrganizationSidebarBrandingPatchSchema, D as CreateCredentialInstanceBodySchema, Dn as WorkflowSummaryListResponseSchema, Dt as PollRunResponseSchema, E as CreateApiKeyResponseSchema, En as WorkflowSummaryDetailResponseSchema, Et as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, F as CreateProjectRequestSchema, Fn as detectProjectPackageManagerFromSnapshot, Ft as ProjectReachabilityResponseSchema, G as DownloadActiveProjectArtifactResponseSchema, Gn as slugifyAppName, Gt as SkillSummaryDetailResponseSchema, H as CredentialInstanceListResponseSchema, Ht as QueuedRunResponseSchema, I as CreateProjectResponseSchema, In as isAcceptableInstallExit, It as ProjectResponseSchema, J as GatewayAttachmentRecordSchema, Jt as StartKeystrokeConnectionInputSchema, K as DownloadActiveProjectSourceResponseSchema, Kt as SkillSummaryListResponseSchema, L as CredentialAssignmentListQuerySchema, Ln as listenPortFromPublicUrl, Lt as ProjectSettingsResponseSchema, M as CreateOrganizationRequestSchema, Mn as WorkspaceTriggerRunListResponseSchema, Mt as PresignUserAvatarRequestSchema, N as CreateOrganizationResponseSchema, Nn as buildConnectDeeplink, Nt as PresignUserAvatarResponseSchema, O as CreateCredentialsRequestSchema, On as WorkspaceTriggerDetailSchema, Ot as PresignOrgLogoRequestSchema, P as CreateProjectArtifactResponseSchema, Pt as ProjectPullStateSchema, Q as HealthResponseSchema, Qt as StartOAuthConnectionInputSchema, R as CredentialAssignmentListResponseSchema, Rt as ProjectSlugAvailabilityResponseSchema, S as CompleteProjectArtifactResponseSchema, Sn as UserPreferencesSchema, St as OpenApiDiscoverResponseSchema, T as CreateApiKeyRequestSchema, Tn as WorkflowRunListResponseSchema, Tt as PROJECT_PULL_STATE_RELATIVE_PATH, U as CredentialInstanceRecordSchema, Un as resolveConnectAppSlug, V as CredentialConsumerListResponseSchema, Vn as parseErrorResponse, Vt as QueuedAgentPromptResponseSchema, W as DeclineOrganizationInvitationResponseSchema, Wn as resolvePublicPlatformOrigin, Wt as RecentResourceListResponseSchema, X as GetCustomAppResponseSchema, Xt as StartMcpOAuthConnectionInputSchema, Y as GetCredentialResponseSchema, Yt as StartKeystrokeConnectionResultSchema, Z as GraphqlDiscoverResponseSchema, Zt as StartMcpOAuthConnectionResultSchema, _ as ChannelAccountListResponseSchema, _n as UploadProjectSourceResponseSchema, _t as ListProjectFilesResponseSchema, a as AgentSessionDetailResponseSchema, an as TriggerRunListResponseSchema, at as InviteProjectMembersRequestSchema, b as ChannelDirectoryListResponseSchema, bn as UserAvatarSchema, bt as ListProjectsResponseSchema, c as AgentSummaryListResponseSchema, cn as UpdateCredentialRequestSchema, ct as ListAgentMemoryFilesResponseSchema, d as AssignCredentialBodySchema, dn as UpdateOrganizationRequestSchema, dt as ListAppsResponseSchema, en as SubmitMarketingContactRequestSchema, et as HistoryRunDetailResponseSchema, f as BindChannelBodySchema, fn as UpdateProjectMemberRequestSchema, ft as ListCredentialsResponseSchema, g as CatalogAppsPageResponseSchema, gn as UploadProjectSourceManifestRequestSchema, gt as ListProjectDeploymentsResponseSchema, h as CatalogAppDetailResponseSchema, hn as UpdateProjectSettingsRequestSchema, ht as ListOrganizationsResponseSchema, i as AgentSessionChatStateResponseSchema, in as TriggerRunDetailResponseSchema, it as InviteOrganizationMembersResponseSchema, j as CreateCustomAppResponseSchema, jn as WorkspaceTriggerOverviewSchema, jt as PresignProjectSourceResponseSchema, k as CreateCredentialsResponseSchema, kn as WorkspaceTriggerFileSchema, kt as PresignOrgLogoResponseSchema, l as AgentTriggerSummaryListResponseSchema, ln as UpdateOrganizationMemberRequestSchema, lt as ListAgentWorkspaceFilesResponseSchema, m as CatalogActionsPageResponseSchema, mn as UpdateProjectRequestSchema, mt as ListOrganizationMembersResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nn as TriggerDetailResponseSchema, nt as HistoryRunListResponseSchema, o as AgentSessionListResponseSchema, on as UpdateChannelBindingBodySchema, ot as InviteProjectMembersResponseSchema, p as CatalogActionDetailResponseSchema, pn as UpdateProjectMemberResponseSchema, pt as ListOrganizationInvitationsResponseSchema, q as ErrorResponseSchema, qt as SlugAvailabilityResponseSchema, r as ActiveOrganizationResponseSchema, rn as TriggerListResponseSchema, rt as InviteOrganizationMembersRequestSchema, s as AgentSummaryDetailResponseSchema, sn as UpdateCredentialInstanceBodySchema, t as ACTIVE_ORG_HEADER, tn as SubmitTeamRequestRequestSchema, tt as HistoryRunListQuerySchema, u as AppSlugAvailabilityResponseSchema, un as UpdateOrganizationMemberResponseSchema, ut as ListApiKeysResponseSchema, v as ChannelConnectionListResponseSchema, vn as UpsertGatewayAttachmentBodySchema, vt as ListProjectMembersResponseSchema, w as ConnectProvidersResponseSchema, wn as WorkflowRunHooksResponseSchema, wt as OrganizationSidebarBrandingSchema, x as ChannelPlatformSchema, xn as UserPreferencesPatchSchema, xt as McpDiscoverResponseSchema, y as ChannelConnectionSchema, yn as UserAvatarPatchSchema, yt as ListProjectMetricsResponseSchema, z as CredentialAssignmentRecordSchema, zt as PromptInputSchema } from "./dist-BnIugffH.mjs";
3
- import { a as installPlaygroundDependencies, c as createCliConfig, d as getEffectiveApiTarget, f as getPlatformUrl, g as resolvePlatformUrlForWebUrl, i as installDependencies$1, l as getCliConfigDir, m as DEFAULT_PLATFORM_URL, n as buildPlaygroundWorkspace, o as resolvePackageManager, p as getWebUrl, s as resolveCliRoot, t as readCliVersion, u as getConfigDir } from "./version-DScIhncv.mjs";
4
- import { n as mergeFilteredArtifact, r as packProjectArtifact, t as mapInParallelBatches } from "./dist-B4pkCJsM.mjs";
2
+ import { $ as HistoryRunCancelResponseSchema, $t as StartMcpOAuthConnectionResultSchema, A as CreateCustomAppRequestSchema, An as WorkspaceTriggerDetailSchema, At as PresignOrgLogoRequestSchema, B as CredentialConsumerListQuerySchema, Bn as listenPortFromPublicUrl, Bt as ProjectSlugAvailabilityResponseSchema, C as ConnectAuthorizeUrlResponseSchema, Cn as UserPreferencesPatchSchema, Ct as OrganizationSidebarBrandingPatchSchema, D as CreateCredentialInstanceBodySchema, Dn as WorkflowRunListResponseSchema, Dt as PollRunResponseSchema, E as CreateApiKeyResponseSchema, En as WorkflowRunHooksResponseSchema, Et as PROJECT_REACHABILITY_REQUEST_TIMEOUT_MS, F as CreateProjectRequestSchema, Fn as buildConnectDeeplink, Ft as PresignUserAvatarResponseSchema, G as DownloadActiveProjectArtifactResponseSchema, H as CredentialInstanceListResponseSchema, Ht as PromptResponseSchema, I as CreateProjectResponseSchema, It as ProjectPullStateSchema, J as GatewayAttachmentRecordSchema, Jn as slugifyAppName, Jt as SkillSummaryListResponseSchema, K as DownloadActiveProjectSourceResponseSchema, Kn as resolveConnectAppSlug, Kt as RecentResourceListResponseSchema, L as CredentialAssignmentListQuerySchema, Ln as deriveCustomAppDisplay, Lt as ProjectReachabilityResponseSchema, M as CreateOrganizationRequestSchema, Mn as WorkspaceTriggerListResponseSchema, Mt as PresignProjectSourceRequestSchema, N as CreateOrganizationResponseSchema, Nn as WorkspaceTriggerOverviewSchema, Nt as PresignProjectSourceResponseSchema, O as CreateCredentialsRequestSchema, On as WorkflowSummaryDetailResponseSchema, Ot as PresignChatAttachmentRequestSchema, P as CreateProjectArtifactResponseSchema, Pn as WorkspaceTriggerRunListResponseSchema, Pt as PresignUserAvatarRequestSchema, Q as HealthResponseSchema, Qt as StartMcpOAuthConnectionInputSchema, R as CredentialAssignmentListResponseSchema, Rn as detectProjectPackageManagerFromSnapshot, Rt as ProjectResponseSchema, S as CompleteProjectArtifactResponseSchema, Sn as UserAvatarSchema, St as OpenApiDiscoverResponseSchema, T as CreateApiKeyRequestSchema, Tn as WorkflowRunDetailResponseSchema, Tt as PROJECT_PULL_STATE_RELATIVE_PATH, U as CredentialInstanceRecordSchema, Un as parseAppSlug, Ut as QueuedAgentPromptResponseSchema, V as CredentialConsumerListResponseSchema, Vt as PromptInputSchema, W as DeclineOrganizationInvitationResponseSchema, Wn as parseErrorResponse, Wt as QueuedRunResponseSchema, X as GetCustomAppResponseSchema, Xt as StartKeystrokeConnectionInputSchema, Y as GetCredentialResponseSchema, Yt as SlugAvailabilityResponseSchema, Z as GraphqlDiscoverResponseSchema, Zt as StartKeystrokeConnectionResultSchema, _ as ChannelAccountListResponseSchema, _n as UpdateProjectSettingsRequestSchema, _t as ListProjectFilesResponseSchema, a as AgentSessionDetailResponseSchema, an as TriggerListResponseSchema, at as InviteProjectMembersRequestSchema, b as ChannelDirectoryListResponseSchema, bn as UpsertGatewayAttachmentBodySchema, bt as ListProjectsResponseSchema, c as AgentSummaryListResponseSchema, cn as UpdateChannelBindingBodySchema, ct as ListAgentMemoryFilesResponseSchema, d as AssignCredentialBodySchema, dn as UpdateOrganizationMemberRequestSchema, dt as ListAppsResponseSchema, en as StartOAuthConnectionInputSchema, et as HistoryRunDetailResponseSchema, f as BindChannelBodySchema, fn as UpdateOrganizationMemberResponseSchema, ft as ListCredentialsResponseSchema, g as CatalogAppsPageResponseSchema, gn as UpdateProjectRequestSchema, gt as ListProjectDeploymentsResponseSchema, h as CatalogAppDetailResponseSchema, hn as UpdateProjectMemberResponseSchema, ht as ListOrganizationsResponseSchema, i as AgentSessionChatStateResponseSchema, in as TriggerDetailResponseSchema, it as InviteOrganizationMembersResponseSchema, j as CreateCustomAppResponseSchema, jn as WorkspaceTriggerFileSchema, jt as PresignOrgLogoResponseSchema, k as CreateCredentialsResponseSchema, kn as WorkflowSummaryListResponseSchema, kt as PresignChatAttachmentResponseSchema, l as AgentTriggerSummaryListResponseSchema, ln as UpdateCredentialInstanceBodySchema, lt as ListAgentWorkspaceFilesResponseSchema, m as CatalogActionsPageResponseSchema, mn as UpdateProjectMemberRequestSchema, mt as ListOrganizationMembersResponseSchema, n as AcceptOrganizationInvitationResponseSchema, nn as SubmitMarketingContactRequestSchema, nt as HistoryRunListResponseSchema, o as AgentSessionListResponseSchema, on as TriggerRunDetailResponseSchema, ot as InviteProjectMembersResponseSchema, p as CatalogActionDetailResponseSchema, pn as UpdateOrganizationRequestSchema, pt as ListOrganizationInvitationsResponseSchema, q as ErrorResponseSchema, qn as resolvePublicPlatformOrigin, qt as SkillSummaryDetailResponseSchema, r as ActiveOrganizationResponseSchema, rn as SubmitTeamRequestRequestSchema, rt as InviteOrganizationMembersRequestSchema, s as AgentSummaryDetailResponseSchema, sn as TriggerRunListResponseSchema, t as ACTIVE_ORG_HEADER, tn as StartOAuthConnectionResultSchema, tt as HistoryRunListQuerySchema, u as AppSlugAvailabilityResponseSchema, un as UpdateCredentialRequestSchema, ut as ListApiKeysResponseSchema, v as ChannelConnectionListResponseSchema, vn as UploadProjectSourceManifestRequestSchema, vt as ListProjectMembersResponseSchema, w as ConnectProvidersResponseSchema, wn as UserPreferencesSchema, wt as OrganizationSidebarBrandingSchema, x as ChannelPlatformSchema, xn as UserAvatarPatchSchema, xt as McpDiscoverResponseSchema, y as ChannelConnectionSchema, yn as UploadProjectSourceResponseSchema, yt as ListProjectMetricsResponseSchema, z as CredentialAssignmentRecordSchema, zn as isAcceptableInstallExit, zt as ProjectSettingsResponseSchema } from "./dist-CNZVjlhC.mjs";
3
+ import { a as installPlaygroundDependencies, c as createCliConfig, d as getEffectiveApiTarget, f as getPlatformUrl, g as resolvePlatformUrlForWebUrl, i as installDependencies$1, l as getCliConfigDir, m as DEFAULT_PLATFORM_URL, n as buildPlaygroundWorkspace, o as resolvePackageManager, p as getWebUrl, s as resolveCliRoot, t as readCliVersion, u as getConfigDir } from "./version-Dv-7vfQn.mjs";
4
+ import { n as mergeFilteredArtifact, r as packProjectArtifact, t as mapInParallelBatches } from "./dist-RRjysgkw.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { Command } from "commander";
7
7
  import { platform } from "node:os";
@@ -3655,6 +3655,15 @@ function createAgentsResource(http) {
3655
3655
  throw await toPlatformError(error);
3656
3656
  }
3657
3657
  },
3658
+ async presignAttachment(projectId, agentSlug, input) {
3659
+ try {
3660
+ const payload = PresignChatAttachmentRequestSchema.parse(input);
3661
+ const data = await http.post(`api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentSlug)}/attachments/presign`, { json: payload }).json();
3662
+ return PresignChatAttachmentResponseSchema.parse(data);
3663
+ } catch (error) {
3664
+ throw await toPlatformError(error);
3665
+ }
3666
+ },
3658
3667
  async getSessionState(projectId, sessionId, options) {
3659
3668
  try {
3660
3669
  const sinceSeq = options?.sinceSeq;
@@ -5366,25 +5375,117 @@ function collectValues$1(value, previous) {
5366
5375
  }
5367
5376
  //#endregion
5368
5377
  //#region src/commands/app/run-app-create.ts
5369
- async function runAppCreate(client, input) {
5378
+ async function runAppCreate(client, input, options) {
5379
+ if (options?.preview) return {
5380
+ preview: true,
5381
+ request: input,
5382
+ slug: await client.apps.checkSlug(input.slug)
5383
+ };
5370
5384
  return client.apps.create(input);
5371
5385
  }
5372
5386
  //#endregion
5387
+ //#region src/commands/app/run-app-create-from-url.ts
5388
+ async function discoverApp(client, source, url) {
5389
+ switch (source) {
5390
+ case "mcp": return client.apps.discoverMcp({ url });
5391
+ case "openapi": return client.apps.discoverOpenApi({ url });
5392
+ case "graphql": return client.apps.discoverGraphql({ url });
5393
+ }
5394
+ }
5395
+ function buildCreateRequest(input, template) {
5396
+ const derived = deriveCustomAppDisplay(template, {
5397
+ url: input.url,
5398
+ mcp: input.source === "mcp"
5399
+ });
5400
+ const name = input.name?.trim() || derived.name;
5401
+ const description = input.description?.trim() || derived.description;
5402
+ const slug = input.slug?.trim() || slugifyAppName(name);
5403
+ const authKind = input.authKind ?? template.authKind;
5404
+ return {
5405
+ name,
5406
+ slug,
5407
+ description,
5408
+ source: input.source,
5409
+ url: input.url,
5410
+ authKind,
5411
+ ...input.fields ? { fields: input.fields } : template.credentialFields ? { fields: template.credentialFields } : {},
5412
+ ...template.credentialScheme ? { credentialScheme: template.credentialScheme } : {},
5413
+ ...authKind === "oauth" && template.oauthScopes.length > 0 ? { oauthScopes: template.oauthScopes } : {}
5414
+ };
5415
+ }
5416
+ async function runAppCreateFromUrl(client, input) {
5417
+ if (input.authKind && input.source !== "mcp") throw new Error("--auth is only supported with --mcp");
5418
+ const discovery = await discoverApp(client, input.source, input.url);
5419
+ if (!discovery.detected) throw new Error(input.source === "mcp" ? "Couldn't reach this MCP server. Check the URL and try again." : input.source === "openapi" ? "Couldn't read this OpenAPI spec. Check the URL and try again." : "Couldn't introspect this GraphQL endpoint. Check the URL and try again.");
5420
+ const request = buildCreateRequest(input, discovery.template);
5421
+ if (input.preview) return {
5422
+ preview: true,
5423
+ detected: true,
5424
+ request,
5425
+ slug: await client.apps.checkSlug(request.slug)
5426
+ };
5427
+ return client.apps.create(request);
5428
+ }
5429
+ //#endregion
5373
5430
  //#region src/commands/app/create.ts
5431
+ function resolveDiscoverSource(options) {
5432
+ const sources = [
5433
+ options.mcp ? {
5434
+ source: "mcp",
5435
+ url: options.mcp
5436
+ } : null,
5437
+ options.openapi ? {
5438
+ source: "openapi",
5439
+ url: options.openapi
5440
+ } : null,
5441
+ options.graphql ? {
5442
+ source: "graphql",
5443
+ url: options.graphql
5444
+ } : null
5445
+ ].filter((entry) => entry !== null);
5446
+ if (sources.length > 1) throw new Error("Use only one of --mcp, --openapi, or --graphql");
5447
+ return sources[0] ?? null;
5448
+ }
5449
+ function parseAuthKind(value) {
5450
+ if (!value) return;
5451
+ if (value === "oauth" || value === "api_key") return value;
5452
+ throw new Error("--auth must be oauth or api_key");
5453
+ }
5454
+ function parseFieldOverrides(flags) {
5455
+ if (flags.length === 0) return;
5456
+ return parseCustomAppFields(flags);
5457
+ }
5374
5458
  function registerAppCreateCommand(app) {
5375
- app.command("create").description("Create a custom org api_key app").requiredOption("--name <name>", "App display name").option("--slug <slug>", "App slug segment (defaults from name)").requiredOption("--description <description>", "App description").option("--field <field>", "Credential field as key, key:secret, key:optional, or key:secret:optional (repeatable)", collectValues$1, []).action((options) => runCliCommand("Create app failed", async () => {
5459
+ app.command("create").description("Create a custom org app").option("--name <name>", "App display name").option("--slug <slug>", "App slug segment (defaults from name)").option("--description <description>", "App description").option("--field <field>", "Credential field as key, key:secret, key:optional, or key:secret:optional (repeatable)", collectValues$1, []).option("--mcp <url>", "Create from an MCP server URL (auto-detect auth)").option("--openapi <url>", "Create from an OpenAPI spec URL (auto-detect auth)").option("--graphql <url>", "Create from a GraphQL endpoint URL (auto-detect auth)").option("--auth <kind>", "Override detected auth: oauth or api_key (MCP only)").option("--preview", "Show the request that would be created without creating").action((options) => runCliCommand("Create app failed", async () => {
5376
5460
  const config = createCliConfig();
5377
5461
  const client = createCliPlatformClient(config);
5378
5462
  await ensureActiveOrganization(config);
5463
+ const discovery = resolveDiscoverSource(options);
5464
+ if (discovery) {
5465
+ const result = await runAppCreateFromUrl(client, {
5466
+ source: discovery.source,
5467
+ url: discovery.url.trim(),
5468
+ name: options.name,
5469
+ slug: options.slug,
5470
+ description: options.description,
5471
+ authKind: parseAuthKind(options.auth),
5472
+ fields: parseFieldOverrides(options.field),
5473
+ preview: options.preview ?? false
5474
+ });
5475
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5476
+ return;
5477
+ }
5478
+ if (!options.name?.trim()) throw new Error("--name is required for custom apps");
5479
+ if (!options.description?.trim()) throw new Error("--description is required for custom apps");
5379
5480
  const slug = options.slug?.trim() || slugifyAppName(options.name);
5380
- const created = await runAppCreate(client, {
5481
+ const result = await runAppCreate(client, {
5381
5482
  name: options.name.trim(),
5382
5483
  slug,
5383
- description: options.description,
5484
+ description: options.description.trim(),
5384
5485
  source: "custom",
5385
5486
  fields: parseCustomAppFields(options.field)
5386
- });
5387
- process.stdout.write(`${JSON.stringify(created, null, 2)}\n`);
5487
+ }, { preview: options.preview ?? false });
5488
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5388
5489
  }, void 0, { orgScoped: true }));
5389
5490
  }
5390
5491
  //#endregion
@@ -6105,7 +6206,7 @@ function registerBuildCommand(program) {
6105
6206
  program.command("build").description("Build the keystroke project for production").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
6106
6207
  try {
6107
6208
  const root = resolveProjectRoot(options.dir);
6108
- const { buildApp } = await import("./dist-PBiyADK0.mjs");
6209
+ const { buildApp } = await import("./dist-DR8DYUc4.mjs");
6109
6210
  await buildApp({ root });
6110
6211
  process.stdout.write(`Built ${root}\n`);
6111
6212
  } catch (error) {
@@ -6159,7 +6260,7 @@ async function sleep(ms) {
6159
6260
  }
6160
6261
  async function buildDeployArchive(client, root, projectId, filter) {
6161
6262
  if (filter?.length) {
6162
- const { buildFilteredApp } = await import("./dist-PBiyADK0.mjs");
6263
+ const { buildFilteredApp } = await import("./dist-DR8DYUc4.mjs");
6163
6264
  const filtered = await buildFilteredApp({
6164
6265
  root,
6165
6266
  filter,
@@ -6181,7 +6282,7 @@ async function buildDeployArchive(client, root, projectId, filter) {
6181
6282
  sourceFiles: filtered.sourceFiles
6182
6283
  };
6183
6284
  }
6184
- const { buildApp } = await import("./dist-PBiyADK0.mjs");
6285
+ const { buildApp } = await import("./dist-DR8DYUc4.mjs");
6185
6286
  const { sourceFiles } = await buildApp({
6186
6287
  root,
6187
6288
  collectSources: true,
@@ -6300,7 +6401,7 @@ function runtimeChildEnv(parentEnv, overrides) {
6300
6401
  //#region src/project/bootstrap-run.ts
6301
6402
  /** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
6302
6403
  async function resolveBootstrapRun(options) {
6303
- const { resolveRuntimeBuildArtifact } = await import("./dist-PBiyADK0.mjs");
6404
+ const { resolveRuntimeBuildArtifact } = await import("./dist-DR8DYUc4.mjs");
6304
6405
  const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
6305
6406
  const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/standalone-bootstrap.mjs");
6306
6407
  const args = [`--import=${loader}`];
@@ -6449,7 +6550,7 @@ async function runDev(options) {
6449
6550
  process.on("SIGINT", shutdown);
6450
6551
  process.on("SIGTERM", shutdown);
6451
6552
  try {
6452
- const { watchApp } = await import("./dist-PBiyADK0.mjs");
6553
+ const { watchApp } = await import("./dist-DR8DYUc4.mjs");
6453
6554
  await watchApp({
6454
6555
  root,
6455
6556
  clean: false,
@@ -6599,7 +6700,7 @@ const INIT_CATALOG_VERSIONS = {
6599
6700
  vitest: "^4.1.7",
6600
6701
  "@types/node": "^25.9.1"
6601
6702
  };
6602
- const INIT_KEYSTROKE_VERSION = "^0.1.14";
6703
+ const INIT_KEYSTROKE_VERSION = "^0.1.16";
6603
6704
  //#endregion
6604
6705
  //#region src/init/copy-template.ts
6605
6706
  function renderTemplate(content, variables) {
@@ -7384,7 +7485,7 @@ async function runStart(options) {
7384
7485
  const apiPort = Number(new URL(serverUrl).port || 80);
7385
7486
  const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
7386
7487
  ensureNativeDeps(runtimeNodeModules);
7387
- const { buildApp } = await import("./dist-PBiyADK0.mjs");
7488
+ const { buildApp } = await import("./dist-DR8DYUc4.mjs");
7388
7489
  await buildApp({
7389
7490
  root,
7390
7491
  clean: false
@@ -7968,7 +8069,7 @@ function createProgram() {
7968
8069
  return program;
7969
8070
  }
7970
8071
  async function runCli(argv) {
7971
- const { maybeAutoUpdate } = await import("./maybe-auto-update-BIarxWf3.mjs");
8072
+ const { maybeAutoUpdate } = await import("./maybe-auto-update-BNvizwom.mjs");
7972
8073
  await maybeAutoUpdate(argv);
7973
8074
  createProgram().parse(argv);
7974
8075
  }