artbot 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/file-system.ts", "../../src/setup/env.ts", "../../src/setup/auth.ts", "../../src/setup/workflow.ts", "../../src/setup/backend.ts", "../../src/setup/health.ts"],
4
+ "sourcesContent": ["import fs from \"node:fs\";\n\nexport function pathExists(filePath: string): boolean {\n try {\n fs.accessSync(filePath, fs.constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function readTextFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport function statFile(filePath: string): fs.Stats | null {\n try {\n return fs.statSync(filePath);\n } catch {\n return null;\n }\n}\n", "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { config as loadDotenv } from \"dotenv\";\nimport type { AuthProfile, SetupWizardValues } from \"./types.js\";\n\ninterface SetupProfileBlueprint {\n id: string;\n mode: AuthProfile[\"mode\"];\n sourceName: string;\n sourcePatterns: string[];\n}\n\nconst SETUP_PROFILE_BLUEPRINTS: SetupProfileBlueprint[] = [\n {\n id: \"artsy-auth\",\n mode: \"authorized\",\n sourceName: \"Artsy\",\n sourcePatterns: [\"artsy\"]\n },\n {\n id: \"mutualart-auth\",\n mode: \"authorized\",\n sourceName: \"MutualArt\",\n sourcePatterns: [\"mutualart\"]\n },\n {\n id: \"sanatfiyat-license\",\n mode: \"licensed\",\n sourceName: \"Sanatfiyat\",\n sourcePatterns: [\"sanatfiyat\"]\n },\n {\n id: \"askart-license\",\n mode: \"licensed\",\n sourceName: \"askART\",\n sourcePatterns: [\"askart\"]\n }\n];\n\nconst CLI_MODULE_DIR = fileURLToPath(new URL(\".\", import.meta.url));\nlet loadedEnvPath: string | null = null;\n\nfunction formatEnvValue(value: string): string {\n if (/^[A-Za-z0-9_./,:-]+$/.test(value)) {\n return value;\n }\n\n if (!value.includes(\"'\") && !value.includes(\"\\n\") && !value.includes(\"\\r\")) {\n return `'${value}'`;\n }\n\n return JSON.stringify(value);\n}\n\nfunction isWorkspaceRoot(directory: string): boolean {\n return fs.existsSync(path.join(directory, \"pnpm-workspace.yaml\")) || fs.existsSync(path.join(directory, \"turbo.json\"));\n}\n\nfunction coerceSearchDirectory(candidate: string): string {\n const resolved = path.resolve(candidate);\n\n try {\n return fs.statSync(resolved).isDirectory() ? resolved : path.dirname(resolved);\n } catch {\n return path.extname(resolved) ? path.dirname(resolved) : resolved;\n }\n}\n\nfunction findWorkspaceRoot(candidate: string): string | null {\n let current = coerceSearchDirectory(candidate);\n\n while (true) {\n if (isWorkspaceRoot(current)) {\n return current;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return null;\n }\n\n current = parent;\n }\n}\n\nexport function detectWorkspaceRoot(cwd = process.cwd()): string | null {\n const candidates = [\n process.env.INIT_CWD,\n cwd,\n process.env.ARTBOT_ROOT,\n process.env.RUNS_ROOT,\n process.env.DATABASE_PATH,\n CLI_MODULE_DIR\n ].filter((candidate): candidate is string => Boolean(candidate && candidate.trim().length > 0));\n\n for (const candidate of candidates) {\n const workspaceRoot = findWorkspaceRoot(candidate);\n if (workspaceRoot) {\n return workspaceRoot;\n }\n }\n\n return null;\n}\n\nexport function resolveWorkspaceRoot(cwd = process.cwd()): string {\n return detectWorkspaceRoot(cwd) ?? path.resolve(cwd);\n}\n\nexport function hasLocalBackendWorkspace(cwd = process.cwd()): boolean {\n const workspaceRoot = detectWorkspaceRoot(cwd);\n if (!workspaceRoot) {\n return false;\n }\n\n return (\n fs.existsSync(path.join(workspaceRoot, \"apps\", \"api\", \"package.json\")) &&\n fs.existsSync(path.join(workspaceRoot, \"apps\", \"worker\", \"package.json\"))\n );\n}\n\nexport function resolveEnvFilePath(cwd = process.cwd()): string {\n return path.resolve(resolveWorkspaceRoot(cwd), \".env\");\n}\n\nexport function loadWorkspaceEnv(cwd = process.cwd()): string {\n const envPath = resolveEnvFilePath(cwd);\n if (loadedEnvPath === envPath) {\n return envPath;\n }\n\n loadDotenv({ path: envPath, override: false });\n loadedEnvPath = envPath;\n return envPath;\n}\n\nexport function parseBooleanEnv(value: string | undefined, fallback: boolean): boolean {\n if (value == null || value.trim() === \"\") return fallback;\n return value.trim().toLowerCase() === \"true\";\n}\n\nexport function parseCommaSeparatedEnv(value: string | undefined): string[] {\n return (value ?? \"\")\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n}\n\nexport function readEnvFile(envPath: string): string {\n try {\n return fs.readFileSync(envPath, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\nexport function upsertEnvFile(envPath: string, updates: Record<string, string>): void {\n const existing = readEnvFile(envPath);\n const lines = existing.length > 0 ? existing.split(/\\r?\\n/) : [];\n const consumed = new Set<string>();\n\n const nextLines = lines.map((line) => {\n const match = line.match(/^\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=/);\n if (!match) {\n return line;\n }\n\n const key = match[1];\n if (!(key in updates)) {\n return line;\n }\n\n consumed.add(key);\n return `${key}=${formatEnvValue(updates[key])}`;\n });\n\n for (const [key, value] of Object.entries(updates)) {\n if (consumed.has(key)) continue;\n nextLines.push(`${key}=${formatEnvValue(value)}`);\n }\n\n fs.writeFileSync(envPath, `${nextLines.filter(Boolean).join(\"\\n\")}\\n`, \"utf-8\");\n}\n\nexport function buildDefaultAuthProfiles(options: {\n cwd?: string;\n enableOptionalProbes?: boolean;\n enableLicensedIntegrations?: boolean;\n} = {}): AuthProfile[] {\n const cwd = resolveWorkspaceRoot(options.cwd ?? process.cwd());\n const enableOptionalProbes = options.enableOptionalProbes ?? false;\n const enableLicensedIntegrations = options.enableLicensedIntegrations ?? false;\n\n return SETUP_PROFILE_BLUEPRINTS.filter((profile) => {\n if (profile.id === \"artsy-auth\" || profile.id === \"mutualart-auth\") {\n return enableOptionalProbes;\n }\n return enableLicensedIntegrations;\n }).map((profile) => ({\n id: profile.id,\n mode: profile.mode,\n sourcePatterns: profile.sourcePatterns,\n storageStatePath: path.resolve(cwd, \"playwright\", \".auth\", `${profile.id}.json`)\n }));\n}\n\nexport function buildSetupEnvUpdates(values: SetupWizardValues): Record<string, string> {\n return {\n LLM_BASE_URL: values.llmBaseUrl,\n API_BASE_URL: values.apiBaseUrl,\n ENABLE_OPTIONAL_PROBE_ADAPTERS: String(values.enableOptionalProbes),\n ENABLE_LICENSED_INTEGRATIONS: String(values.enableLicensedIntegrations),\n DEFAULT_LICENSED_INTEGRATIONS: values.defaultLicensedIntegrations.join(\",\"),\n DEFAULT_AUTH_PROFILE: \"\",\n AUTH_PROFILES_JSON: JSON.stringify(values.authProfiles)\n };\n}\n\nexport function defaultSourceUrlForProfile(profileId: string): string {\n switch (profileId) {\n case \"artsy-auth\":\n return \"https://www.artsy.net\";\n case \"mutualart-auth\":\n return \"https://www.mutualart.com\";\n case \"sanatfiyat-license\":\n return \"https://www.sanatfiyat.com\";\n case \"askart-license\":\n return \"https://www.askart.com\";\n default:\n return \"https://example.com\";\n }\n}\n", "import path from \"node:path\";\nimport { pathExists, statFile } from \"../lib/file-system.js\";\nimport { loadWorkspaceEnv } from \"./env.js\";\nimport type {\n AuthCaptureCommand,\n AuthProfile,\n AuthProfileSessionState,\n AuthProfilesError,\n AuthRelevantProfile,\n ParseAuthProfilesResult\n} from \"./types.js\";\n\nfunction normalizeSourcePattern(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction buildAuthProfilesParseCandidates(rawValue: string): string[] {\n const trimmed = rawValue.trim();\n const candidates = [trimmed];\n const pushCandidate = (candidate: string) => {\n if (candidate.length > 0 && !candidates.includes(candidate)) {\n candidates.push(candidate);\n }\n };\n\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n pushCandidate(trimmed.slice(1, -1));\n }\n\n for (const candidate of [...candidates]) {\n const repaired = candidate.replace(/\\\\\"/g, '\"');\n if (repaired !== candidate) {\n pushCandidate(repaired);\n }\n }\n\n return candidates;\n}\n\nexport function parseAuthProfilesJson(rawValue: string | undefined): ParseAuthProfilesResult {\n if (!rawValue || rawValue.trim().length === 0) {\n return { profiles: [], error: null };\n }\n\n try {\n let parsed: unknown;\n let parsedSuccessfully = false;\n let lastError: unknown;\n\n for (const candidate of buildAuthProfilesParseCandidates(rawValue)) {\n try {\n parsed = candidate;\n for (let depth = 0; depth < 3 && typeof parsed === \"string\"; depth += 1) {\n parsed = JSON.parse(parsed) as unknown;\n }\n parsedSuccessfully = true;\n break;\n } catch (error) {\n lastError = error;\n }\n }\n\n if (!parsedSuccessfully) {\n throw (lastError ?? new Error(\"AUTH_PROFILES_JSON is not valid JSON.\"));\n }\n\n if (!Array.isArray(parsed)) {\n return {\n profiles: [],\n error: {\n message: \"AUTH_PROFILES_JSON must be a JSON array.\",\n rawValue\n }\n };\n }\n\n const profiles: AuthProfile[] = [];\n for (const [index, entry] of parsed.entries()) {\n if (!entry || typeof entry !== \"object\") {\n return {\n profiles: [],\n error: {\n message: `AUTH_PROFILES_JSON entry ${index} is not an object.`,\n rawValue\n }\n };\n }\n\n const candidate = entry as Partial<AuthProfile>;\n if (typeof candidate.id !== \"string\" || candidate.id.trim().length === 0) {\n return {\n profiles: [],\n error: {\n message: `AUTH_PROFILES_JSON entry ${index} is missing a valid id.`,\n rawValue\n }\n };\n }\n\n if (candidate.mode !== \"authorized\" && candidate.mode !== \"licensed\") {\n return {\n profiles: [],\n error: {\n message: `AUTH_PROFILES_JSON entry ${index} has invalid mode \"${String(candidate.mode)}\".`,\n rawValue\n }\n };\n }\n\n if (!Array.isArray(candidate.sourcePatterns) || candidate.sourcePatterns.some((pattern: unknown) => typeof pattern !== \"string\")) {\n return {\n profiles: [],\n error: {\n message: `AUTH_PROFILES_JSON entry ${index} must define sourcePatterns as an array of strings.`,\n rawValue\n }\n };\n }\n\n profiles.push({\n id: candidate.id.trim(),\n mode: candidate.mode,\n sourcePatterns: candidate.sourcePatterns.map((pattern: string) => pattern.trim()).filter(Boolean),\n cookieFile: candidate.cookieFile,\n usernameEnv: candidate.usernameEnv,\n passwordEnv: candidate.passwordEnv,\n apiKeyEnv: candidate.apiKeyEnv,\n storageStatePath: candidate.storageStatePath,\n sessionTtlMinutes: candidate.sessionTtlMinutes\n });\n }\n\n return { profiles, error: null };\n } catch (error) {\n return {\n profiles: [],\n error: {\n message: \"AUTH_PROFILES_JSON is not valid JSON.\",\n details: error instanceof Error ? error.message : String(error),\n rawValue\n }\n };\n }\n}\n\nexport function resolveAuthProfilesFromEnv(env: NodeJS.ProcessEnv = process.env): ParseAuthProfilesResult {\n if (env === process.env) {\n loadWorkspaceEnv();\n }\n return parseAuthProfilesJson(env.AUTH_PROFILES_JSON);\n}\n\nexport function resolveStorageStatePath(profile: AuthProfile, cwd = process.cwd()): string {\n return profile.storageStatePath ? path.resolve(cwd, profile.storageStatePath) : path.resolve(cwd, \"playwright\", \".auth\", `${profile.id}.json`);\n}\n\nexport function inspectSessionState(profile: AuthProfile, cwd = process.cwd(), now = new Date()): AuthProfileSessionState {\n const storageStatePath = resolveStorageStatePath(profile, cwd);\n const exists = pathExists(storageStatePath);\n const stat = exists ? statFile(storageStatePath) : null;\n const lastModifiedAtIso = stat?.mtime.toISOString() ?? null;\n const ttlMinutes = profile.sessionTtlMinutes ?? 6 * 60;\n\n let expired = true;\n if (exists && stat) {\n expired = now.getTime() - stat.mtime.getTime() > ttlMinutes * 60 * 1000;\n }\n\n return {\n profileId: profile.id,\n storageStatePath,\n exists,\n lastModifiedAtIso,\n expired\n };\n}\n\nexport function inspectSessionStates(profiles: AuthProfile[], cwd = process.cwd(), now = new Date()): AuthProfileSessionState[] {\n return profiles.map((profile) => inspectSessionState(profile, cwd, now));\n}\n\nexport function findAuthRelevantProfiles(profiles: AuthProfile[], sourceNames: string[]): AuthRelevantProfile[] {\n const loweredSources = sourceNames.map(normalizeSourcePattern);\n\n return profiles\n .map((profile) => {\n const matchedSources = loweredSources.filter((source) =>\n profile.sourcePatterns.some((pattern: string) => {\n try {\n return new RegExp(pattern, \"i\").test(source);\n } catch {\n return source.includes(normalizeSourcePattern(pattern));\n }\n })\n );\n return { profile, matchedSources };\n })\n .filter((entry) => entry.matchedSources.length > 0);\n}\n\nexport function buildAuthCaptureCommand(profile: AuthProfile, sourceUrl: string, storageStatePath = resolveStorageStatePath(profile)): AuthCaptureCommand {\n const command = `artbot auth capture ${profile.id}`;\n return {\n profileId: profile.id,\n sourceUrl,\n storageStatePath,\n command\n };\n}\n\nexport function buildAuthCaptureCommands(profiles: AuthProfile[], sourceUrlByProfileId: Record<string, string> = {}): AuthCaptureCommand[] {\n return profiles.map((profile) => buildAuthCaptureCommand(profile, sourceUrlByProfileId[profile.id] ?? \"https://example.com\", resolveStorageStatePath(profile)));\n}\n\nexport function formatAuthProfilesError(error: AuthProfilesError | null): string | null {\n if (!error) return null;\n return error.details ? `${error.message} ${error.details}` : error.message;\n}\n", "import * as clack from \"@clack/prompts\";\nimport picocolors from \"picocolors\";\nimport { buildAuthCaptureCommand, findAuthRelevantProfiles, inspectSessionStates, parseAuthProfilesJson } from \"./auth.js\";\nimport { startLocalBackendServices } from \"./backend.js\";\nimport {\n buildDefaultAuthProfiles,\n buildSetupEnvUpdates,\n detectWorkspaceRoot,\n defaultSourceUrlForProfile,\n hasLocalBackendWorkspace,\n loadWorkspaceEnv,\n parseBooleanEnv,\n parseCommaSeparatedEnv,\n resolveEnvFilePath,\n resolveWorkspaceRoot,\n upsertEnvFile\n} from \"./env.js\";\nimport { checkApiHealth, checkLlmHealth } from \"./health.js\";\nimport type { SetupAssessment, SetupIssue, SetupWizardValues, StartedBackendServices } from \"./types.js\";\n\nfunction createIssue(severity: SetupIssue[\"severity\"], code: string, message: string, detail?: string): SetupIssue {\n return { severity, code, message, detail };\n}\n\nexport async function assessLocalSetup(env: NodeJS.ProcessEnv = process.env, cwd = process.cwd()): Promise<SetupAssessment> {\n if (env === process.env) {\n loadWorkspaceEnv(cwd);\n }\n\n const workspaceRoot = detectWorkspaceRoot(cwd);\n const resolvedCwd = resolveWorkspaceRoot(cwd);\n const envPath = resolveEnvFilePath(resolvedCwd);\n const localBackendAvailable = hasLocalBackendWorkspace(cwd);\n const llmBaseUrl = env.LLM_BASE_URL?.trim() || \"http://127.0.0.1:1234/v1\";\n const apiBaseUrl = env.API_BASE_URL?.trim() || \"http://localhost:4000\";\n const llmHealth = await checkLlmHealth(llmBaseUrl, env.LLM_API_KEY ?? env.OPENAI_API_KEY ?? \"lm-studio\");\n const apiHealth = await checkApiHealth(apiBaseUrl, env.ARTBOT_API_KEY);\n const parsedProfiles = parseAuthProfilesJson(env.AUTH_PROFILES_JSON);\n const profiles = parsedProfiles.profiles;\n const enableOptionalProbes = parseBooleanEnv(env.ENABLE_OPTIONAL_PROBE_ADAPTERS, false);\n const enableLicensedIntegrations = parseBooleanEnv(env.ENABLE_LICENSED_INTEGRATIONS, false);\n const enabledSourceNames = [\n ...(enableOptionalProbes ? [\"Artsy\", \"MutualArt\", \"askART\"] : []),\n ...(enableLicensedIntegrations ? [\"Sanatfiyat\"] : [])\n ];\n const relevantProfiles = findAuthRelevantProfiles(profiles, enabledSourceNames);\n const sessionStates = inspectSessionStates(relevantProfiles.map((entry) => entry.profile), resolvedCwd);\n\n const issues: SetupIssue[] = [];\n if (!llmHealth.ok) {\n issues.push(createIssue(\"error\", \"llm_unreachable\", \"LM Studio is not reachable.\", llmHealth.reason));\n }\n if (!apiHealth.ok) {\n issues.push(createIssue(\"warning\", \"api_unreachable\", \"ArtBot API is not reachable.\", apiHealth.reason));\n if (!localBackendAvailable) {\n issues.push(\n createIssue(\n \"warning\",\n \"local_backend_unavailable\",\n \"Local backend auto-start is unavailable outside the ArtBot repo.\",\n \"Set API_BASE_URL to a running ArtBot API.\"\n )\n );\n }\n }\n if (parsedProfiles.error) {\n issues.push(createIssue(\"error\", \"auth_profiles_invalid\", parsedProfiles.error.message, parsedProfiles.error.details));\n }\n if (enabledSourceNames.length > 0 && profiles.length === 0) {\n issues.push(createIssue(\"warning\", \"auth_profiles_missing\", \"Auth-capable sources are enabled but no auth profiles are configured.\"));\n }\n\n for (const session of sessionStates) {\n if (!session.exists) {\n issues.push(createIssue(\"warning\", \"auth_session_missing\", `Missing browser session for ${session.profileId}.`, session.storageStatePath));\n continue;\n }\n if (session.expired) {\n issues.push(createIssue(\"warning\", \"auth_session_expired\", `Saved browser session expired for ${session.profileId}.`, session.storageStatePath));\n }\n }\n\n return {\n cwd: resolvedCwd,\n workspaceRoot,\n envPath,\n localBackendAvailable,\n llmBaseUrl,\n apiBaseUrl,\n llmHealth,\n apiHealth,\n profiles,\n authProfilesError: parsedProfiles.error,\n relevantProfiles,\n sessionStates,\n issues\n };\n}\n\nexport async function runSetupWizard(cwd = process.cwd()): Promise<{\n assessment: SetupAssessment;\n backendStart: StartedBackendServices | null;\n}> {\n const env = process.env;\n const workspaceRoot = resolveWorkspaceRoot(cwd);\n const localBackendAvailable = hasLocalBackendWorkspace(cwd);\n const llmBaseUrl = await clack.text({\n message: \"LM Studio base URL\",\n initialValue: env.LLM_BASE_URL?.trim() || \"http://127.0.0.1:1234/v1\",\n validate(input) {\n return input.trim().length === 0 ? \"LM Studio URL is required.\" : undefined;\n }\n });\n if (clack.isCancel(llmBaseUrl)) throw new Error(\"Setup cancelled.\");\n\n const apiBaseUrl = await clack.text({\n message: \"ArtBot API base URL\",\n initialValue: env.API_BASE_URL?.trim() || \"http://localhost:4000\",\n validate(input) {\n return input.trim().length === 0 ? \"API URL is required.\" : undefined;\n }\n });\n if (clack.isCancel(apiBaseUrl)) throw new Error(\"Setup cancelled.\");\n\n const enableOptionalProbes = await clack.confirm({\n message: \"Enable optional probe sources (Artsy, MutualArt, askART)?\",\n initialValue: parseBooleanEnv(env.ENABLE_OPTIONAL_PROBE_ADAPTERS, false)\n });\n if (clack.isCancel(enableOptionalProbes)) throw new Error(\"Setup cancelled.\");\n\n const enableLicensedIntegrations = await clack.confirm({\n message: \"Enable licensed integrations?\",\n initialValue: parseBooleanEnv(env.ENABLE_LICENSED_INTEGRATIONS, true)\n });\n if (clack.isCancel(enableLicensedIntegrations)) throw new Error(\"Setup cancelled.\");\n\n const defaultLicensedIntegrations = enableLicensedIntegrations ? [\"Sanatfiyat\"] : [];\n const authProfiles = buildDefaultAuthProfiles({\n cwd: workspaceRoot,\n enableOptionalProbes,\n enableLicensedIntegrations\n });\n\n const values: SetupWizardValues = {\n llmBaseUrl: llmBaseUrl.trim(),\n apiBaseUrl: apiBaseUrl.trim(),\n enableOptionalProbes,\n enableLicensedIntegrations,\n defaultLicensedIntegrations,\n authProfiles\n };\n\n const envPath = resolveEnvFilePath(workspaceRoot);\n upsertEnvFile(envPath, buildSetupEnvUpdates(values));\n clack.log.success(`Updated ${picocolors.bold(envPath)}`);\n\n let backendStart: StartedBackendServices | null = null;\n const apiHealth = await checkApiHealth(values.apiBaseUrl, process.env.ARTBOT_API_KEY);\n if (!apiHealth.ok && localBackendAvailable) {\n const shouldStartBackend = await clack.confirm({\n message: \"ArtBot API is offline. Start local API and worker now?\",\n initialValue: true\n });\n if (clack.isCancel(shouldStartBackend)) throw new Error(\"Setup cancelled.\");\n if (shouldStartBackend) {\n backendStart = startLocalBackendServices(workspaceRoot);\n clack.log.info(`Started local backend. API log: ${backendStart.apiLogPath}`);\n clack.log.info(`Worker log: ${backendStart.workerLogPath}`);\n }\n } else if (!apiHealth.ok) {\n clack.log.info(\"Local backend auto-start is only available inside the ArtBot repo.\");\n clack.log.info(\"Set API_BASE_URL to a running ArtBot API or start the services manually.\");\n }\n\n const captureNow = authProfiles.length > 0\n ? await clack.confirm({\n message: \"Capture browser login sessions now?\",\n initialValue: false\n })\n : false;\n\n if (clack.isCancel(captureNow)) throw new Error(\"Setup cancelled.\");\n if (captureNow) {\n for (const profile of authProfiles) {\n const shouldCaptureProfile = await clack.confirm({\n message: `Capture session for ${profile.id}?`,\n initialValue: !profile.id.startsWith(\"artsy\") && !profile.id.startsWith(\"askart\")\n });\n if (clack.isCancel(shouldCaptureProfile)) throw new Error(\"Setup cancelled.\");\n if (!shouldCaptureProfile) continue;\n const command = buildAuthCaptureCommand(profile, defaultSourceUrlForProfile(profile.id));\n clack.log.message(`${picocolors.cyan(\"Auth capture\")}: ${command.command}`);\n }\n }\n\n const assessment = await assessLocalSetup(process.env, workspaceRoot);\n return { assessment, backendStart };\n}\n\nexport function resolveSetupWizardDefaults(env: NodeJS.ProcessEnv = process.env): SetupWizardValues {\n if (env === process.env) {\n loadWorkspaceEnv();\n }\n\n const enableOptionalProbes = parseBooleanEnv(env.ENABLE_OPTIONAL_PROBE_ADAPTERS, false);\n const enableLicensedIntegrations = parseBooleanEnv(env.ENABLE_LICENSED_INTEGRATIONS, false);\n return {\n llmBaseUrl: env.LLM_BASE_URL?.trim() || \"http://127.0.0.1:1234/v1\",\n apiBaseUrl: env.API_BASE_URL?.trim() || \"http://localhost:4000\",\n enableOptionalProbes,\n enableLicensedIntegrations,\n defaultLicensedIntegrations: parseCommaSeparatedEnv(env.DEFAULT_LICENSED_INTEGRATIONS),\n authProfiles: parseAuthProfilesJson(env.AUTH_PROFILES_JSON).profiles\n };\n}\n", "import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport type { LocalBackendProcessCommand, StartedBackendServices } from \"./types.js\";\nimport { hasLocalBackendWorkspace, resolveWorkspaceRoot } from \"./env.js\";\n\nexport interface BackendStartMetadata {\n api: LocalBackendProcessCommand;\n worker: LocalBackendProcessCommand;\n apiHealthPath: string;\n recommendedEntryCommand: string;\n}\n\nexport function resolveBackendStartMetadata(cwd = process.cwd(), apiBaseUrl = \"http://localhost:4000\"): BackendStartMetadata {\n const workspaceRoot = resolveWorkspaceRoot(cwd);\n return {\n api: {\n service: \"api\",\n command: \"pnpm --filter @artbot/api dev\",\n cwd: workspaceRoot,\n displayName: \"ArtBot API\"\n },\n worker: {\n service: \"worker\",\n command: \"pnpm --filter @artbot/worker dev\",\n cwd: workspaceRoot,\n displayName: \"ArtBot worker\"\n },\n apiHealthPath: `${apiBaseUrl.replace(/\\/$/, \"\")}/health`,\n recommendedEntryCommand: \"pnpm run start:artbot\"\n };\n}\n\nexport function formatBackendStartMetadata(metadata: BackendStartMetadata): string {\n return [\n `${metadata.api.displayName}: ${metadata.api.command}`,\n `${metadata.worker.displayName}: ${metadata.worker.command}`,\n `Health check: ${metadata.apiHealthPath}`,\n `Entry point: ${metadata.recommendedEntryCommand}`\n ].join(\"\\n\");\n}\n\nexport function resolveAuthCaptureWorkspacePath(profileId: string, cwd = process.cwd()): string {\n return path.resolve(resolveWorkspaceRoot(cwd), \"playwright\", \".auth\", `${profileId}.json`);\n}\n\nfunction spawnDetachedProcess(command: string, cwd: string, logPath: string): number {\n const logFd = fs.openSync(logPath, \"a\");\n const child = spawn(command, {\n cwd,\n shell: true,\n detached: true,\n stdio: [\"ignore\", logFd, logFd]\n });\n child.unref();\n fs.closeSync(logFd);\n return child.pid ?? -1;\n}\n\nexport function startLocalBackendServices(cwd = process.cwd()): StartedBackendServices {\n if (!hasLocalBackendWorkspace(cwd)) {\n throw new Error(\"Local backend auto-start is only available from an ArtBot workspace checkout.\");\n }\n\n const workspaceRoot = resolveWorkspaceRoot(cwd);\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const logDir = path.resolve(workspaceRoot, \".artbot-logs\");\n fs.mkdirSync(logDir, { recursive: true });\n\n const apiLogPath = path.join(logDir, `api-${stamp}.log`);\n const workerLogPath = path.join(logDir, `worker-${stamp}.log`);\n\n const metadata = resolveBackendStartMetadata(workspaceRoot);\n const apiPid = spawnDetachedProcess(metadata.api.command, workspaceRoot, apiLogPath);\n const workerPid = spawnDetachedProcess(metadata.worker.command, workspaceRoot, workerLogPath);\n\n return {\n logDir,\n apiLogPath,\n workerLogPath,\n apiPid,\n workerPid\n };\n}\n", "import type { ApiHealthResult, LlmHealthResult } from \"./types.js\";\n\nasync function fetchWithTimeout(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function checkLlmHealth(\n baseUrl: string,\n apiKey = \"\",\n timeoutMs = 1500\n): Promise<LlmHealthResult> {\n const headers: Record<string, string> = {};\n if (apiKey) {\n headers.authorization = `Bearer ${apiKey}`;\n }\n\n try {\n const response = await fetchWithTimeout(`${baseUrl.replace(/\\/$/, \"\")}/models`, { headers }, timeoutMs);\n if (!response.ok) {\n return {\n ok: false,\n baseUrl,\n statusCode: response.status,\n reason: `HTTP ${response.status}`\n };\n }\n\n const payload = (await response.json()) as { data?: Array<{ id?: string }> };\n return {\n ok: true,\n baseUrl,\n modelId: payload.data?.[0]?.id\n };\n } catch (error) {\n return {\n ok: false,\n baseUrl,\n reason: error instanceof Error ? error.message : String(error)\n };\n }\n}\n\nexport async function checkApiHealth(apiBaseUrl: string, apiKey = \"\", timeoutMs = 1500): Promise<ApiHealthResult> {\n const headers: Record<string, string> = {};\n if (apiKey) {\n headers[\"x-api-key\"] = apiKey;\n }\n\n try {\n const response = await fetchWithTimeout(`${apiBaseUrl.replace(/\\/$/, \"\")}/health`, { headers }, timeoutMs);\n if (!response.ok) {\n return {\n ok: false,\n apiBaseUrl,\n statusCode: response.status,\n reason: `HTTP ${response.status}`\n };\n }\n\n return { ok: true, apiBaseUrl };\n } catch (error) {\n return {\n ok: false,\n apiBaseUrl,\n reason: error instanceof Error ? error.message : String(error)\n };\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "fs", "path", "path", "fs", "path", "fs", "path"]
7
+ }