Files
opencode/packages/web/src/pages/s/[id].astro
2026-02-09 11:34:35 -06:00

165 lines
4.9 KiB
Plaintext

---
import { Base64 } from "js-base64"
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro"
import type { Session } from "opencode/session/index"
import config from "../../../config.mjs"
import Share from "../../components/Share.tsx"
const apiUrl = import.meta.env.VITE_API_URL || ""
const ta = Astro.locals.t as ((key: string) => string) & {
all?: () => Record<string, string>
}
const all = typeof ta.all === "function" ? ta.all() : {}
const locale = Astro.currentLocale || Astro.locals.starlightRoute.locale || "root"
const formatLocale = locale === "root" ? "en" : locale
const t = ta
function tx(key: string) {
const value = all[key]
if (typeof value === "string") return value
return t(key)
}
const messages = {
locale: formatLocale,
link_to_message: tx("share.link_to_message"),
copied: tx("share.copied"),
copy: tx("share.copy"),
show_more: tx("share.show_more"),
show_less: tx("share.show_less"),
show_results: tx("share.show_results"),
hide_results: tx("share.hide_results"),
show_details: tx("share.show_details"),
hide_details: tx("share.hide_details"),
show_preview: tx("share.show_preview"),
hide_preview: tx("share.hide_preview"),
show_contents: tx("share.show_contents"),
hide_contents: tx("share.hide_contents"),
show_output: tx("share.show_output"),
hide_output: tx("share.hide_output"),
error: tx("share.error"),
waiting_for_messages: tx("share.waiting_for_messages"),
status_connected_waiting: tx("share.status_connected_waiting"),
status_connecting: tx("share.status_connecting"),
status_disconnected: tx("share.status_disconnected"),
status_reconnecting: tx("share.status_reconnecting"),
status_error: tx("share.status_error"),
status_unknown: tx("share.status_unknown"),
error_id_not_found: tx("share.error_id_not_found"),
error_api_url_not_found: tx("share.error_api_url_not_found"),
error_connection_failed: tx("share.error_connection_failed"),
opencode_version: tx("share.opencode_version"),
opencode_name: tx("share.opencode_name"),
models: tx("share.models"),
cost: tx("share.cost"),
input_tokens: tx("share.input_tokens"),
output_tokens: tx("share.output_tokens"),
reasoning_tokens: tx("share.reasoning_tokens"),
scroll_to_bottom: tx("share.scroll_to_bottom"),
attachment: tx("share.attachment"),
thinking: tx("share.thinking"),
thinking_pending: tx("share.thinking_pending"),
creating_plan: tx("share.creating_plan"),
completing_plan: tx("share.completing_plan"),
updating_plan: tx("share.updating_plan"),
match_one: tx("share.match_one"),
match_other: tx("share.match_other"),
result_one: tx("share.result_one"),
result_other: tx("share.result_other"),
debug_key: tx("share.debug_key"),
}
const id = Astro.params.id || ""
const res = await fetch(`${apiUrl}/share_data?id=${id}`)
const data = (await res.json()) as {
info?: Session.Info
messages: Record<string, { role?: string; modelID?: string }>
}
if (!data.info) {
return new Response(null, {
status: 404,
statusText: tx("share.not_found"),
})
}
const models: Set<string> = new Set()
const version = data.info.version ? `v${data.info.version}` : "v0.0.1"
for (const d of Object.values(data.messages)) {
if (d.role === "assistant" && d.modelID) {
models.add(d.modelID)
}
}
const encodedTitle = encodeURIComponent(
Base64.encode(
encodeURIComponent(data.info.title.substring(0, 700)),
),
)
const modelsArray = Array.from(models)
const modelParam =
modelsArray.length === 1
? modelsArray[0]
: modelsArray.length === 2
? encodeURIComponent(`${modelsArray[0]} & ${modelsArray[1]}`)
: encodeURIComponent(`${modelsArray[0]} & ${modelsArray.length - 1} others`)
const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=${modelParam}&version=${version}&id=${id}`
---
<StarlightPage
hasSidebar={false}
frontmatter={{
title: data.info.title,
pagefind: false,
template: "splash",
tableOfContents: false,
head: [
{
tag: "meta",
attrs: {
name: "description",
content: tx("share.meta_description"),
},
},
{
tag: "meta",
attrs: {
name: "robots",
content: "noindex, nofollow, noarchive, nosnippet",
}
},
{
tag: "meta",
attrs: {
property: "og:image",
content: ogImage,
},
},
{
tag: "meta",
attrs: {
name: "twitter:image",
content: ogImage,
},
},
],
}}
>
<Share id={id} api={apiUrl} info={data.info} messages={messages} client:only="solid" />
</StarlightPage>
<style is:global>
body > .page > .main-frame .main-pane > main > .content-panel:first-of-type {
display: none;
}
body > .page > .main-frame .main-pane > main {
padding: 0;
}
body > .page > .main-frame .main-pane > main > .content-panel + .content-panel {
border-top: none !important;
padding: 0;
}
</style>