mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-22 10:14:22 +01:00
share collapse system prompt
This commit is contained in:
@@ -399,21 +399,12 @@ export default function Share(props: { api: string }) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const models = createMemo(() => {
|
const data = 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 result = {
|
const result = {
|
||||||
|
created: undefined as number | undefined,
|
||||||
|
system: [] as string[],
|
||||||
|
messages: [] as SessionMessage[],
|
||||||
|
models: [] as string[][],
|
||||||
cost: 0,
|
cost: 0,
|
||||||
tokens: {
|
tokens: {
|
||||||
input: 0,
|
input: 0,
|
||||||
@@ -421,16 +412,39 @@ export default function Share(props: { api: string }) {
|
|||||||
reasoning: 0,
|
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
|
const assistant = msg.metadata?.assistant
|
||||||
if (!assistant) continue
|
|
||||||
|
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.cost += assistant.cost
|
||||||
result.tokens.input += assistant.tokens.input
|
result.tokens.input += assistant.tokens.input
|
||||||
result.tokens.output += assistant.tokens.output
|
result.tokens.output += assistant.tokens.output
|
||||||
result.tokens.reasoning += assistant.tokens.reasoning
|
result.tokens.reasoning += assistant.tokens.reasoning
|
||||||
|
|
||||||
|
result.models.push([
|
||||||
|
assistant.providerID,
|
||||||
|
assistant.modelID,
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
const [showingSystemPrompt, showSystemPrompt] = createSignal(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main class={`${styles.root} not-content`}>
|
<main class={`${styles.root} not-content`}>
|
||||||
@@ -439,14 +453,14 @@ export default function Share(props: { api: string }) {
|
|||||||
<h1>{store.info?.title}</h1>
|
<h1>{store.info?.title}</h1>
|
||||||
<div>
|
<div>
|
||||||
<div data-section="date">
|
<div data-section="date">
|
||||||
{messages().length > 0 && messages()[0].metadata?.time.created ? (
|
{data().created ? (
|
||||||
<span
|
<span
|
||||||
title={DateTime.fromMillis(
|
title={DateTime.fromMillis(
|
||||||
messages()[0].metadata?.time.created || 0,
|
data().created || 0,
|
||||||
).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
|
).toLocaleString(DateTime.DATETIME_FULL_WITH_SECONDS)}
|
||||||
>
|
>
|
||||||
{DateTime.fromMillis(
|
{DateTime.fromMillis(
|
||||||
messages()[0].metadata?.time.created || 0,
|
data().created || 0,
|
||||||
).toLocaleString(DateTime.DATE_MED)}
|
).toLocaleString(DateTime.DATE_MED)}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
@@ -465,40 +479,40 @@ export default function Share(props: { api: string }) {
|
|||||||
<ul data-section="stats">
|
<ul data-section="stats">
|
||||||
<li>
|
<li>
|
||||||
<span data-element-label>Cost</span>
|
<span data-element-label>Cost</span>
|
||||||
{metrics().cost !== undefined ? (
|
{data().cost !== undefined ? (
|
||||||
<span>${metrics().cost.toFixed(2)}</span>
|
<span>${data().cost.toFixed(2)}</span>
|
||||||
) : (
|
) : (
|
||||||
<span data-placeholder>—</span>
|
<span data-placeholder>—</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span data-element-label>Input Tokens</span>
|
<span data-element-label>Input Tokens</span>
|
||||||
{metrics().tokens.input ? (
|
{data().tokens.input ? (
|
||||||
<span>{metrics().tokens.input}</span>
|
<span>{data().tokens.input}</span>
|
||||||
) : (
|
) : (
|
||||||
<span data-placeholder>—</span>
|
<span data-placeholder>—</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span data-element-label>Output Tokens</span>
|
<span data-element-label>Output Tokens</span>
|
||||||
{metrics().tokens.output ? (
|
{data().tokens.output ? (
|
||||||
<span>{metrics().tokens.output}</span>
|
<span>{data().tokens.output}</span>
|
||||||
) : (
|
) : (
|
||||||
<span data-placeholder>—</span>
|
<span data-placeholder>—</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span data-element-label>Reasoning Tokens</span>
|
<span data-element-label>Reasoning Tokens</span>
|
||||||
{metrics().tokens.reasoning ? (
|
{data().tokens.reasoning ? (
|
||||||
<span>{metrics().tokens.reasoning}</span>
|
<span>{data().tokens.reasoning}</span>
|
||||||
) : (
|
) : (
|
||||||
<span data-placeholder>—</span>
|
<span data-placeholder>—</span>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul data-section="stats" data-section-models>
|
<ul data-section="stats" data-section-models>
|
||||||
{models().length > 0 ? (
|
{data().models.length > 0 ? (
|
||||||
<For each={Array.from(models())}>
|
<For each={Array.from(data().models)}>
|
||||||
{([provider, model]) => (
|
{([provider, model]) => (
|
||||||
<li>
|
<li>
|
||||||
<div data-stat-model-icon title={provider}>
|
<div data-stat-model-icon title={provider}>
|
||||||
@@ -515,16 +529,44 @@ export default function Share(props: { api: string }) {
|
|||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</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>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Show
|
<Show
|
||||||
when={messages().length > 0}
|
when={data().messages.length > 0}
|
||||||
fallback={<p>Waiting for messages...</p>}
|
fallback={<p>Waiting for messages...</p>}
|
||||||
>
|
>
|
||||||
<div class={styles.parts}>
|
<div class={styles.parts}>
|
||||||
<For each={messages()}>
|
<For each={data().messages}>
|
||||||
{(msg, msgIndex) => (
|
{(msg, msgIndex) => (
|
||||||
<For each={msg.parts}>
|
<For each={msg.parts}>
|
||||||
{(part, partIndex) => {
|
{(part, partIndex) => {
|
||||||
@@ -537,13 +579,9 @@ export default function Share(props: { api: string }) {
|
|||||||
const [results, showResults] = createSignal(false)
|
const [results, showResults] = createSignal(false)
|
||||||
const isLastPart = createMemo(
|
const isLastPart = createMemo(
|
||||||
() =>
|
() =>
|
||||||
messages().length === msgIndex() + 1 &&
|
data().messages.length === msgIndex() + 1 &&
|
||||||
msg.parts.length === partIndex() + 1,
|
msg.parts.length === partIndex() + 1,
|
||||||
)
|
)
|
||||||
const time =
|
|
||||||
msg.metadata?.time.completed ||
|
|
||||||
msg.metadata?.time.created ||
|
|
||||||
0
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
{/* User text */}
|
{/* User text */}
|
||||||
@@ -918,11 +956,11 @@ export default function Share(props: { api: string }) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Show
|
<Show
|
||||||
when={messages().length > 0}
|
when={data().messages.length > 0}
|
||||||
fallback={<p>Waiting for messages...</p>}
|
fallback={<p>Waiting for messages...</p>}
|
||||||
>
|
>
|
||||||
<ul style={{ "list-style-type": "none", padding: 0 }}>
|
<ul style={{ "list-style-type": "none", padding: 0 }}>
|
||||||
<For each={messages()}>
|
<For each={data().messages}>
|
||||||
{(msg) => (
|
{(msg) => (
|
||||||
<li
|
<li
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -8,19 +8,6 @@
|
|||||||
--term-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E");
|
--term-icon: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2060%2016'%20preserveAspectRatio%3D'xMidYMid%20meet'%3E%3Ccircle%20cx%3D'8'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'30'%20cy%3D'8'%20r%3D'8'%2F%3E%3Ccircle%20cx%3D'52'%20cy%3D'8'%20r%3D'8'%2F%3E%3C%2Fsvg%3E");
|
||||||
}
|
}
|
||||||
|
|
||||||
[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-text] {
|
[data-element-button-text] {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
@@ -59,13 +46,18 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
|
|
||||||
|
@media (max-width: 30rem) {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
[data-section="title"] {
|
[data-section="title"] {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 1rem;
|
gap: 3rem;
|
||||||
|
|
||||||
& > div {
|
& > div {
|
||||||
|
flex: 0 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@@ -127,6 +119,11 @@
|
|||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
@media (max-width: 30rem) {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-section="stats"] {
|
[data-section="stats"] {
|
||||||
@@ -163,10 +160,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
span[data-stat-model] {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.parts {
|
.parts {
|
||||||
|
|||||||
Reference in New Issue
Block a user