import { parse as parseYaml } from "yaml"; import type { PreviewItem } from "../../components/share-home-types.ts"; import type { BundleCounts, BundleUrls, Frontmatter, NormalizedBundle, NormalizedCommandItem, NormalizedSkillItem, OpenInAppUrls, RequestLike, ValidationResult, } from "./types.ts"; export const OPENWORK_SITE_URL = "https://openwork.software"; export const OPENWORK_DOWNLOAD_URL = "https://openwork.software/download"; export const DEFAULT_PUBLIC_BASE_URL = "https://share.openwork.software"; export const DEFAULT_OPENWORK_APP_URL = "https://app.openwork.software"; export const SHARE_EASE = "cubic-bezier(0.31, 0.325, 0, 0.92)"; export function maybeString(value: unknown): string { return typeof value === "string" ? value : ""; } export function maybeObject(value: unknown): Record | null { return value && typeof value === "object" && !Array.isArray(value) ? (value as Record) : null; } export function maybeArray(value: unknown): unknown[] { return Array.isArray(value) ? value : []; } export function getEnv(name: string, fallback = ""): string { const value = process.env[name]; return typeof value === "string" && value.trim() ? value.trim() : fallback; } export function normalizeBaseUrl(input: unknown): string { return String(input ?? "").trim().replace(/\/+$/, ""); } export function normalizeAppUrl(input: unknown): string { return normalizeBaseUrl(input); } export function setCors( res: { setHeader(name: string, value: string): void }, options: { methods?: string; headers?: string } = {}, ): void { res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", options.methods ?? "GET,POST,OPTIONS"); res.setHeader( "Access-Control-Allow-Headers", options.headers ?? "Content-Type,Accept,X-OpenWork-Bundle-Type,X-OpenWork-Schema-Version,X-OpenWork-Name", ); } export function readBody(req: NodeJS.ReadableStream): Promise { return new Promise((resolve, reject) => { const chunks: Buffer[] = []; req.on("data", (chunk: Buffer) => chunks.push(chunk)); req.on("end", () => resolve(Buffer.concat(chunks))); req.on("error", reject); }); } export function escapeHtml(value: unknown): string { return String(value) .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } export function escapeJsonForScript(rawJson: string): string { return String(rawJson) .replaceAll("<", "\\u003c") .replaceAll(">", "\\u003e") .replaceAll("\u2028", "\\u2028") .replaceAll("\u2029", "\\u2029"); } export function humanizeType(type: unknown): string { if (!type) return "Bundle"; return String(type) .split("-") .filter(Boolean) .map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`) .join(" "); } export function truncate(value: unknown, maxChars = 3200): string { const text = String(value ?? ""); if (text.length <= maxChars) return text; return `${text.slice(0, maxChars)}\n\n... (truncated for display)`; } function getOrigin(req: RequestLike): string { const protocolHeader = String(req.headers?.["x-forwarded-proto"] ?? "https") .split(",")[0] .trim(); const hostHeader = String(req.headers?.["x-forwarded-host"] ?? req.headers?.host ?? "") .split(",")[0] .trim(); if (!hostHeader) { return normalizeBaseUrl(getEnv("PUBLIC_BASE_URL", DEFAULT_PUBLIC_BASE_URL)); } return `${protocolHeader || "https"}://${hostHeader}`; } export function buildRootUrl(req: RequestLike): string { return normalizeBaseUrl(getOrigin(req)) || DEFAULT_PUBLIC_BASE_URL; } export function buildOgImageUrl(req: RequestLike, targetId = "root"): string { const origin = buildRootUrl(req); return `${origin}/og/${encodeURIComponent(targetId)}`; } export function buildBundleUrls(req: RequestLike, id: string): BundleUrls { const encodedId = encodeURIComponent(id); const origin = buildRootUrl(req); const path = `/b/${encodedId}`; return { shareUrl: `${origin}${path}`, jsonUrl: `${origin}${path}?format=json`, downloadUrl: `${origin}${path}?format=json&download=1`, }; } export function buildOpenInAppUrls(shareUrl: string, options: { label?: string } = {}): OpenInAppUrls { const query = new URLSearchParams(); query.set("ow_bundle", shareUrl); query.set("ow_intent", "new_worker"); query.set("ow_source", "share_service"); const label = String(options.label ?? "").trim(); if (label) query.set("ow_label", label.slice(0, 120)); const openInAppDeepLink = `openwork://import-bundle?${query.toString()}`; const appUrl = normalizeAppUrl(getEnv("PUBLIC_OPENWORK_APP_URL", DEFAULT_OPENWORK_APP_URL)) || DEFAULT_OPENWORK_APP_URL; try { const url = new URL(appUrl); for (const [key, value] of query.entries()) { url.searchParams.set(key, value); } return { openInAppDeepLink, openInWebAppUrl: url.toString(), }; } catch { return { openInAppDeepLink, openInWebAppUrl: `${DEFAULT_OPENWORK_APP_URL}?${query.toString()}`, }; } } export function wantsJsonResponse(req: RequestLike): boolean { const format = String(req.query?.format ?? "").trim().toLowerCase(); if (format === "json") return true; if (format === "html") return false; const accept = String(req.headers?.accept ?? "").toLowerCase(); if (!accept) return true; if (accept.includes("application/json")) return true; if (accept.includes("text/html") || accept.includes("application/xhtml+xml")) return false; return true; } export function wantsDownload(req: RequestLike): boolean { return String(req.query?.download ?? "").trim() === "1"; } export function parseFrontmatter(content: unknown): Frontmatter { const text = String(content ?? ""); const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/); if (!match) return { data: {}, body: text }; const raw = match[1] ?? ""; let data: Record = {}; try { data = maybeObject(parseYaml(raw)) ?? {}; } catch { data = {}; } return { data, body: text.slice(match[0].length) }; } function normalizeSkillItem(value: unknown): NormalizedSkillItem | null { const record = maybeObject(value); if (!record) return null; const name = maybeString(record.name).trim(); const content = maybeString(record.content); if (!name || !content.trim()) return null; return { name, description: maybeString(record.description).trim(), trigger: maybeString(record.trigger).trim(), content, }; } function normalizeCommandItem(value: unknown): NormalizedCommandItem | null { const record = maybeObject(value); if (!record) return null; const name = maybeString(record.name).trim(); const template = maybeString(record.template); const content = maybeString(record.content); if (!name || (!template.trim() && !content.trim())) return null; return { name, description: maybeString(record.description).trim(), template, content, agent: maybeString(record.agent).trim(), model: maybeString(record.model).trim(), subtask: record.subtask === true, }; } export function parseBundle(rawJson: string): NormalizedBundle { try { return normalizeBundleRecord(JSON.parse(rawJson)); } catch { return normalizeBundleRecord(null); } } function normalizeBundleRecord(parsed: unknown): NormalizedBundle { const record = maybeObject(parsed); const workspace = maybeObject(record?.workspace); return { schemaVersion: typeof record?.schemaVersion === "number" ? record.schemaVersion : null, type: maybeString(record?.type).trim(), name: maybeString(record?.name).trim(), description: maybeString(record?.description).trim(), trigger: maybeString(record?.trigger).trim(), content: maybeString(record?.content), workspace, skills: maybeArray(record?.skills).map(normalizeSkillItem).filter((s): s is NormalizedSkillItem => s !== null), commands: maybeArray(record?.commands).map(normalizeCommandItem).filter((c): c is NormalizedCommandItem => c !== null), }; } export function validateBundlePayload(rawJson: string): ValidationResult { let parsed: unknown; try { parsed = JSON.parse(rawJson); } catch { return { ok: false, message: "Invalid JSON" }; } const bundle = normalizeBundleRecord(parsed); if (bundle.schemaVersion !== 1) { return { ok: false, message: "Unsupported bundle schema version" }; } if (!["skill", "skills-set", "workspace-profile"].includes(bundle.type)) { return { ok: false, message: "Unsupported bundle type" }; } if (bundle.type === "skill") { if (!bundle.name || !bundle.content.trim()) { return { ok: false, message: "Skill bundles require name and content" }; } } if (bundle.type === "skills-set") { if (!bundle.skills.length) { return { ok: false, message: "Skills set bundle has no importable skills" }; } } if (bundle.type === "workspace-profile") { if (!bundle.workspace) { return { ok: false, message: "Workspace profile bundle is missing workspace payload" }; } } return { ok: true, bundle }; } export function getBundleCounts(bundle: NormalizedBundle): BundleCounts { const workspaceSkills = maybeArray(bundle.workspace?.skills).map(normalizeSkillItem).filter((s): s is NormalizedSkillItem => s !== null); const opencode = maybeObject(bundle.workspace?.opencode); const openwork = maybeObject(bundle.workspace?.openwork); const genericConfig = maybeObject(bundle.workspace?.config); const commands = maybeArray(bundle.workspace?.commands).map(normalizeCommandItem).filter((c): c is NormalizedCommandItem => c !== null); const agentEntries = Object.entries(maybeObject(opencode?.agent) ?? {}); const mcpEntries = Object.entries(maybeObject(opencode?.mcp) ?? {}); const opencodeConfigKeys = Object.keys(opencode ?? {}).filter((key) => !["agent", "mcp"].includes(key)); return { skillCount: bundle.type === "skill" ? bundle.name ? 1 : 0 : bundle.type === "skills-set" ? bundle.skills.length : workspaceSkills.length, commandCount: commands.length, agentCount: agentEntries.length, mcpCount: mcpEntries.length, configCount: (openwork ? 1 : 0) + (opencodeConfigKeys.length ? 1 : 0) + Object.keys(genericConfig ?? {}).length, hasConfig: Boolean(openwork || opencodeConfigKeys.length || genericConfig), }; } function readVersionFromContent(content: string): string { const { data } = parseFrontmatter(content); const version = maybeString(data.version).trim(); return version || ""; } export function collectBundleItems(bundle: NormalizedBundle, limit = 8): PreviewItem[] { const items: PreviewItem[] = []; if (bundle.type === "skill") { items.push({ name: bundle.name || "Untitled skill", kind: "Skill", meta: bundle.trigger ? `Trigger · ${bundle.trigger}` : readVersionFromContent(bundle.content) || "Skill bundle", tone: "skill", }); } if (bundle.type === "skills-set") { for (const skill of bundle.skills) { items.push({ name: skill.name, kind: "Skill", meta: skill.trigger ? `Trigger · ${skill.trigger}` : readVersionFromContent(skill.content) || "Skill", tone: "skill", }); } } if (bundle.type === "workspace-profile") { const workspaceSkills = maybeArray(bundle.workspace?.skills).map(normalizeSkillItem).filter((s): s is NormalizedSkillItem => s !== null); for (const skill of workspaceSkills) { items.push({ name: skill.name, kind: "Skill", meta: skill.trigger ? `Trigger · ${skill.trigger}` : readVersionFromContent(skill.content) || "Skill", tone: "skill", }); } const opencode = maybeObject(bundle.workspace?.opencode); for (const [name, config] of Object.entries(maybeObject(opencode?.agent) ?? {})) { const entry = maybeObject(config) ?? {}; const version = maybeString(entry.version).trim(); const model = maybeString(entry.model).trim(); items.push({ name, kind: "Agent", meta: version ? `v${version}` : model ? model : "Agent config", tone: "agent", }); } for (const [name, config] of Object.entries(maybeObject(opencode?.mcp) ?? {})) { const entry = maybeObject(config) ?? {}; const type = maybeString(entry.type).trim(); const url = maybeString(entry.url).trim(); items.push({ name, kind: "MCP", meta: type ? `${humanizeType(type)} MCP` : url ? "Remote MCP" : "MCP config", tone: "mcp", }); } const commands = maybeArray(bundle.workspace?.commands).map(normalizeCommandItem).filter((c): c is NormalizedCommandItem => c !== null); for (const command of commands) { items.push({ name: command.name, kind: "Command", meta: command.agent ? `Agent · ${command.agent}` : "Command", tone: "command", }); } const opencodeConfigKeys = Object.keys(maybeObject(opencode) ?? {}).filter((key) => !["agent", "mcp"].includes(key)); if (opencodeConfigKeys.length) { items.push({ name: "opencode.json", kind: "Config", meta: "OpenCode config", tone: "config", }); } if (maybeObject(bundle.workspace?.openwork)) { items.push({ name: "openwork.json", kind: "Config", meta: "OpenWork config", tone: "config", }); } for (const [name] of Object.entries(maybeObject(bundle.workspace?.config) ?? {})) { items.push({ name, kind: "Config", meta: "Config file", tone: "config", }); } } return items.slice(0, limit); } const PREVIEW_MAX_CHARS = 2200; function slugifyPreviewFilename(value: string, fallback: string, extension: string): string { const stem = String(value ?? "") .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, ""); return `${stem || fallback}.${extension}`; } function buildTextPreview(content: string, fallback: string): string { const normalized = String(content ?? "").trim(); return truncate(normalized || fallback, PREVIEW_MAX_CHARS); } function buildJsonPreview(value: unknown, fallback: string): string { try { const serialized = JSON.stringify(value, null, 2); return truncate(serialized || fallback, PREVIEW_MAX_CHARS); } catch { return fallback; } } function buildBundlePreviewSelection(input: { filename: string; text: string; tone: PreviewItem["tone"]; label: string; }): { filename: string; text: string; tone: PreviewItem["tone"]; label: string; } { return input; } export function buildBundlePreview(bundle: NormalizedBundle): { filename: string; text: string; tone: PreviewItem["tone"]; label: string; } { if (bundle.type === "skill") { return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(bundle.name || "skill", "skill", "md"), text: buildTextPreview(bundle.content, `# ${bundle.name || "OpenWork skill"}`), tone: "skill", label: bundle.trigger ? `Trigger: ${bundle.trigger}` : "Skill preview", }); } if (bundle.type === "skills-set" && bundle.skills.length) { const firstSkill = bundle.skills[0]!; return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(firstSkill.name || "skill", "skill", "md"), text: buildTextPreview(firstSkill.content, `# ${firstSkill.name || "Shared skill"}`), tone: "skill", label: bundle.skills.length > 1 ? `First of ${bundle.skills.length} skills` : "Skill preview", }); } const workspaceSkills = maybeArray(bundle.workspace?.skills).map(normalizeSkillItem).filter((skill): skill is NormalizedSkillItem => skill !== null); if (workspaceSkills.length) { const firstSkill = workspaceSkills[0]!; return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(firstSkill.name || "skill", "skill", "md"), text: buildTextPreview(firstSkill.content, `# ${firstSkill.name || "Workspace skill"}`), tone: "skill", label: workspaceSkills.length > 1 ? `Lead skill of ${workspaceSkills.length}` : "Skill preview", }); } const commands = maybeArray(bundle.workspace?.commands).map(normalizeCommandItem).filter((command): command is NormalizedCommandItem => command !== null); if (commands.length) { const firstCommand = commands[0]!; return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(firstCommand.name || "command", "command", "md"), text: buildTextPreview(firstCommand.template || firstCommand.content, `# ${firstCommand.name || "OpenWork command"}`), tone: "command", label: firstCommand.agent ? `Command for ${firstCommand.agent}` : "Command preview", }); } const opencode = maybeObject(bundle.workspace?.opencode); const agentEntries = Object.entries(maybeObject(opencode?.agent) ?? {}); if (agentEntries.length) { const [name, config] = agentEntries[0]!; return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(name, "agent", "json"), text: buildJsonPreview({ agent: { [name]: config } }, '{\n "agent": {}\n}'), tone: "agent", label: "Agent config", }); } const mcpEntries = Object.entries(maybeObject(opencode?.mcp) ?? {}); if (mcpEntries.length) { const [name, config] = mcpEntries[0]!; return buildBundlePreviewSelection({ filename: slugifyPreviewFilename(name, "mcp", "json"), text: buildJsonPreview({ mcp: { [name]: config } }, '{\n "mcp": {}\n}'), tone: "mcp", label: "MCP config", }); } if (maybeObject(bundle.workspace?.openwork)) { return buildBundlePreviewSelection({ filename: "openwork.json", text: buildJsonPreview(bundle.workspace?.openwork, '{\n "openwork": {}\n}'), tone: "config", label: "OpenWork config", }); } if (opencode) { return buildBundlePreviewSelection({ filename: "opencode.json", text: buildJsonPreview(opencode, '{\n "opencode": {}\n}'), tone: "config", label: "OpenCode config", }); } const configEntries = Object.entries(maybeObject(bundle.workspace?.config) ?? {}); if (configEntries.length) { const [name, value] = configEntries[0]!; const extension = name.includes(".") ? name.split(".").pop() || "json" : "json"; return buildBundlePreviewSelection({ filename: name, text: buildJsonPreview(value, `{\n "${name}": {}\n}`), tone: "config", label: `Config preview · ${extension}`, }); } return buildBundlePreviewSelection({ filename: "bundle.json", text: buildJsonPreview(bundle, '{\n "bundle": true\n}'), tone: "config", label: "Bundle JSON", }); } export function prettyJson(rawJson: string): string { try { return JSON.stringify(JSON.parse(rawJson), null, 2); } catch { return rawJson; } } export function buildBundleNarrative(bundle: NormalizedBundle): string { const counts = getBundleCounts(bundle); if (bundle.type === "skill") { return "One reusable skill, wrapped in a share link that opens directly into a new OpenWork worker."; } if (bundle.type === "skills-set") { return `${counts.skillCount} skills packaged together so a new worker can start with the full set in one import.`; } const parts: string[] = []; if (counts.skillCount) parts.push(`${counts.skillCount} skill${counts.skillCount === 1 ? "" : "s"}`); if (counts.agentCount) parts.push(`${counts.agentCount} agent${counts.agentCount === 1 ? "" : "s"}`); if (counts.mcpCount) parts.push(`${counts.mcpCount} MCP${counts.mcpCount === 1 ? "" : "s"}`); if (counts.commandCount) parts.push(`${counts.commandCount} command${counts.commandCount === 1 ? "" : "s"}`); if (counts.configCount) parts.push(`${counts.configCount} config${counts.configCount === 1 ? "" : "s"}`); return parts.length ? `${parts.join(", ")} bundled into a worker package that imports through OpenWork with one step.` : "Worker configuration bundle prepared for OpenWork import."; } export function buildStatusMarkup({ title, description, actionHref, actionLabel, }: { title: string; description: string; actionHref?: string; actionLabel?: string; }): string { return ` ${escapeHtml(title)} - OpenWork Share

${escapeHtml(title)}

${escapeHtml(description)}

${actionHref && actionLabel ? `${escapeHtml(actionLabel)}` : ""}
`; }