summaryrefslogtreecommitdiffhomepage
path: root/packages/web/src
diff options
context:
space:
mode:
authorJay V <[email protected]>2025-06-04 13:37:03 -0400
committerJay V <[email protected]>2025-06-04 13:37:07 -0400
commit484c90ed0093139c853792b4b3bff76092ea2ea8 (patch)
tree204a8a2ade1d8bd689a384bd15a86062fbe24863 /packages/web/src
parentf49694a5436ba99a9c9184d9afd77ff1b7ea0f9a (diff)
downloadopencode-484c90ed0093139c853792b4b3bff76092ea2ea8.tar.gz
opencode-484c90ed0093139c853792b4b3bff76092ea2ea8.zip
share collapse system prompt
Diffstat (limited to 'packages/web/src')
-rw-r--r--packages/web/src/components/Share.tsx122
-rw-r--r--packages/web/src/components/share.module.css51
2 files changed, 116 insertions, 57 deletions
diff --git a/packages/web/src/components/Share.tsx b/packages/web/src/components/Share.tsx
index 99ed3e130..619b88747 100644
--- a/packages/web/src/components/Share.tsx
+++ b/packages/web/src/components/Share.tsx
@@ -399,21 +399,12 @@ export default function Share(props: { api: string }) {
})
})
- const models = createMemo(() => {
- const result: string[][] = []
- for (const msg of messages()) {
- if (msg.role === "assistant" && msg.metadata?.assistant) {
- result.push([
- msg.metadata.assistant.providerID,
- msg.metadata.assistant.modelID,
- ])
- }
- }
- return result
- })
-
- const metrics = createMemo(() => {
+ const data = createMemo(() => {
const result = {
+ created: undefined as number | undefined,
+ system: [] as string[],
+ messages: [] as SessionMessage[],
+ models: [] as string[][],
cost: 0,
tokens: {
input: 0,
@@ -421,16 +412,39 @@ export default function Share(props: { api: string }) {
reasoning: 0,
},
}
- for (const msg of messages()) {
+ for (let i = 0; i < messages().length; i++) {
+ const msg = messages()[i]
+
+ const system = i === 0 && msg.role === "system"
const assistant = msg.metadata?.assistant
- if (!assistant) continue
- result.cost += assistant.cost
- result.tokens.input += assistant.tokens.input
- result.tokens.output += assistant.tokens.output
- result.tokens.reasoning += assistant.tokens.reasoning
+
+ if (system) {
+ for (const part of msg.parts) {
+ if (part.type === "text") {
+ result.system.push(part.text)
+ }
+ }
+ result.created = msg.metadata?.time.created
+ continue
+ }
+
+ result.messages.push(msg)
+
+ if (assistant) {
+ result.cost += assistant.cost
+ result.tokens.input += assistant.tokens.input
+ result.tokens.output += assistant.tokens.output
+ result.tokens.reasoning += assistant.tokens.reasoning
+
+ result.models.push([
+ assistant.providerID,
+ assistant.modelID,
+ ])
+ }
}
return result
})
+ const [showingSystemPrompt, showSystemPrompt] = createSignal(false)
return (
<main class={`${styles.root} not-content`}>
@@ -439,14 +453,14 @@ export default function Share(props: { api: string }) {
<h1>{store.info?.title}</h1>
<div>
<div data-section="date">
- {messages().length > 0 && messages()[0].metadata?.time.created ? (
+ {data().created ? (
<span
title={DateTime.fromMillis(
- messages()[0].metadata?.time.created || 0,
+ data().created || 0,
).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
>
{DateTime.fromMillis(
- messages()[0].metadata?.time.created || 0,
+ data().created || 0,
).toLocaleString(DateTime.DATE_MED)}
</span>
) : (
@@ -465,40 +479,40 @@ export default function Share(props: { api: string }) {
<ul data-section="stats">
<li>
<span data-element-label>Cost</span>
- {metrics().cost !== undefined ? (
- <span>${metrics().cost.toFixed(2)}</span>
+ {data().cost !== undefined ? (
+ <span>${data().cost.toFixed(2)}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>Input Tokens</span>
- {metrics().tokens.input ? (
- <span>{metrics().tokens.input}</span>
+ {data().tokens.input ? (
+ <span>{data().tokens.input}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>Output Tokens</span>
- {metrics().tokens.output ? (
- <span>{metrics().tokens.output}</span>
+ {data().tokens.output ? (
+ <span>{data().tokens.output}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
<li>
<span data-element-label>Reasoning Tokens</span>
- {metrics().tokens.reasoning ? (
- <span>{metrics().tokens.reasoning}</span>
+ {data().tokens.reasoning ? (
+ <span>{data().tokens.reasoning}</span>
) : (
<span data-placeholder>&mdash;</span>
)}
</li>
</ul>
<ul data-section="stats" data-section-models>
- {models().length > 0 ? (
- <For each={Array.from(models())}>
+ {data().models.length > 0 ? (
+ <For each={Array.from(data().models)}>
{([provider, model]) => (
<li>
<div data-stat-model-icon title={provider}>
@@ -515,16 +529,44 @@ export default function Share(props: { api: string }) {
</li>
)}
</ul>
+ <div data-section="system-prompt">
+ <div data-section="icon">
+ <IconCpuChip width={16} height={16} />
+ </div>
+ <div data-section="content">
+ <button
+ type="button"
+ data-element-button-text
+ data-element-button-more
+ onClick={() => showSystemPrompt((e) => !e)}
+ >
+ <span>
+ {showingSystemPrompt() ? "Hide system prompt" : "Show system prompt"}
+ </span>
+ <span data-button-icon>
+ <Show
+ when={showingSystemPrompt()}
+ fallback={<IconChevronRight width={12} height={12} />}
+ >
+ <IconChevronDown width={12} height={12} />
+ </Show>
+ </span>
+ </button>
+ <Show when={showingSystemPrompt()}>
+ <TextPart data-size="sm" expand text={data().system.join("\n")} />
+ </Show>
+ </div>
+ </div>
</div>
</div>
<div>
<Show
- when={messages().length > 0}
+ when={data().messages.length > 0}
fallback={<p>Waiting for messages...</p>}
>
<div class={styles.parts}>
- <For each={messages()}>
+ <For each={data().messages}>
{(msg, msgIndex) => (
<For each={msg.parts}>
{(part, partIndex) => {
@@ -537,13 +579,9 @@ export default function Share(props: { api: string }) {
const [results, showResults] = createSignal(false)
const isLastPart = createMemo(
() =>
- messages().length === msgIndex() + 1 &&
+ data().messages.length === msgIndex() + 1 &&
msg.parts.length === partIndex() + 1,
)
- const time =
- msg.metadata?.time.completed ||
- msg.metadata?.time.created ||
- 0
return (
<Switch>
{/* User text */}
@@ -918,11 +956,11 @@ export default function Share(props: { api: string }) {
}}
>
<Show
- when={messages().length > 0}
+ when={data().messages.length > 0}
fallback={<p>Waiting for messages...</p>}
>
<ul style={{ "list-style-type": "none", padding: 0 }}>
- <For each={messages()}>
+ <For each={data().messages}>
{(msg) => (
<li
style={{
diff --git a/packages/web/src/components/share.module.css b/packages/web/src/components/share.module.css
index 8de8953a4..9cd17ddeb 100644
--- a/packages/web/src/components/share.module.css
+++ b/packages/web/src/components/share.module.css
@@ -19,19 +19,6 @@
&:hover {
color: var(--sl-color-text);
}
-}
-
-[data-element-button-text] {
- cursor: pointer;
- appearance: none;
- background-color: transparent;
- border: none;
- padding: 0;
- color: var(--sl-color-text-secondary);
-
- &:hover {
- color: var(--sl-color-text);
- }
&[data-element-button-more] {
display: flex;
@@ -59,13 +46,18 @@
flex-direction: column;
gap: 0.75rem;
+ @media (max-width: 30rem) {
+ gap: 1rem;
+ }
+
[data-section="title"] {
display: flex;
align-items: center;
justify-content: space-between;
- gap: 1rem;
+ gap: 3rem;
& > div {
+ flex: 0 0 auto;
display: flex;
flex-direction: column;
gap: 0.5rem;
@@ -127,6 +119,11 @@
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
+
+ @media (max-width: 30rem) {
+ font-size: 1.25rem;
+ -webkit-line-clamp: 3;
+ }
}
[data-section="stats"] {
@@ -163,9 +160,33 @@
}
span[data-stat-model] {
- color: var(sl-color-text);
+ color: var(--sl-color-text);
+ }
+ }
+ }
+ [data-section="system-prompt"] {
+ display: flex;
+ gap: 0.3125rem;
+
+ [data-section="icon"] {
+ flex: 0 0 auto;
+ color: var(--sl-color-text-dimmed);
+ opacity: 0.85;
+ svg {
+ display: block;
}
}
+
+ [data-section="content"] {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ }
+
+ button {
+ line-height: 1rem;
+ font-size: 0.875rem;
+ }
}
}