|
4 | 4 | import CodegenToolCalls from '$components/codegen/CodegenToolCalls.svelte';
|
5 | 5 | import CodegenUserMessage from '$components/codegen/CodegenUserMessage.svelte';
|
6 | 6 | import { type Message } from '$lib/codegen/messages';
|
| 7 | + import { Icon, Markdown } from '@gitbutler/ui'; |
7 | 8 |
|
8 | 9 | type Props = {
|
9 | 10 | message: Message;
|
|
12 | 13 | userAvatarUrl?: string;
|
13 | 14 | };
|
14 | 15 | const { message, onApproval, onRejection, userAvatarUrl }: Props = $props();
|
| 16 | +
|
| 17 | + let expanded = $state(false); |
15 | 18 | </script>
|
16 | 19 |
|
17 | 20 | {#if message.type === 'user'}
|
18 | 21 | <CodegenUserMessage content={message.message} avatarUrl={userAvatarUrl} />
|
19 | 22 | {:else if message.type === 'claude'}
|
20 |
| - <CodegenAssistantMessage content={message.message}> |
21 |
| - {#snippet extraContent()} |
22 |
| - <CodegenToolCalls toolCalls={message.toolCalls} /> |
23 |
| - |
24 |
| - {#if message.toolCallsPendingApproval.length > 0} |
25 |
| - {#each message.toolCallsPendingApproval as toolCall} |
26 |
| - <CodegenToolCall |
27 |
| - style="standalone" |
28 |
| - {toolCall} |
29 |
| - requiresApproval={{ |
30 |
| - onApproval: async (id) => await onApproval?.(id), |
31 |
| - onRejection: async (id) => await onRejection?.(id) |
32 |
| - }} |
33 |
| - /> |
34 |
| - {/each} |
35 |
| - {/if} |
36 |
| - {/snippet} |
37 |
| - </CodegenAssistantMessage> |
| 23 | + {#if 'subtype' in message && message.subtype === 'compaction'} |
| 24 | + <CodegenAssistantMessage content="The conversation has been compacted."> |
| 25 | + {#snippet extraContent()} |
| 26 | + {@render compactionSummary(message.message)} |
| 27 | + {/snippet} |
| 28 | + </CodegenAssistantMessage> |
| 29 | + {:else} |
| 30 | + <CodegenAssistantMessage content={message.message}> |
| 31 | + {#snippet extraContent()} |
| 32 | + <CodegenToolCalls toolCalls={message.toolCalls} /> |
| 33 | + |
| 34 | + {#if message.toolCallsPendingApproval.length > 0} |
| 35 | + {#each message.toolCallsPendingApproval as toolCall} |
| 36 | + <CodegenToolCall |
| 37 | + style="standalone" |
| 38 | + {toolCall} |
| 39 | + requiresApproval={{ |
| 40 | + onApproval: async (id) => await onApproval?.(id), |
| 41 | + onRejection: async (id) => await onRejection?.(id) |
| 42 | + }} |
| 43 | + /> |
| 44 | + {/each} |
| 45 | + {/if} |
| 46 | + {/snippet} |
| 47 | + </CodegenAssistantMessage> |
| 48 | + {/if} |
38 | 49 | {/if}
|
| 50 | + |
| 51 | +{#snippet compactionSummary(summary: string)} |
| 52 | + <div class="compaction-summary__wrapper"> |
| 53 | + <div class="compaction-summary" class:expanded> |
| 54 | + <!-- Header for multiple tool calls --> |
| 55 | + <button |
| 56 | + type="button" |
| 57 | + class="compaction-summary__header" |
| 58 | + onclick={() => (expanded = !expanded)} |
| 59 | + > |
| 60 | + <div class="compaction-summary__arrow" class:expanded> |
| 61 | + <Icon name="chevron-right" /> |
| 62 | + </div> |
| 63 | + <span class="text-13 text-semibold">Compaction summary</span> |
| 64 | + </button> |
| 65 | + {#if expanded} |
| 66 | + <div class="compaction-summary__content"> |
| 67 | + <Markdown content={summary} /> |
| 68 | + </div> |
| 69 | + {/if} |
| 70 | + </div> |
| 71 | + </div> |
| 72 | +{/snippet} |
| 73 | + |
| 74 | +<style lang="postcss"> |
| 75 | + .compaction-summary__wrapper { |
| 76 | + container-name: assistant-message; |
| 77 | + container-type: inline-size; |
| 78 | + } |
| 79 | +
|
| 80 | + .compaction-summary { |
| 81 | + width: fit-content; |
| 82 | + max-width: var(--message-max-width); |
| 83 | + max-width: 100%; |
| 84 | + overflow: hidden; |
| 85 | + border: 1px solid var(--clr-border-2); |
| 86 | + border-radius: var(--radius-ml); |
| 87 | +
|
| 88 | + &.expanded { |
| 89 | + width: 100%; |
| 90 | + } |
| 91 | + } |
| 92 | +
|
| 93 | + .compaction-summary__header { |
| 94 | + display: flex; |
| 95 | + align-items: center; |
| 96 | + width: 100%; |
| 97 | + padding: 8px 12px 8px 8px; |
| 98 | + gap: 8px; |
| 99 | + border: none; |
| 100 | + cursor: pointer; |
| 101 | + transition: background-color var(--transition-fast); |
| 102 | +
|
| 103 | + &:hover { |
| 104 | + background-color: var(--clr-bg-1-muted); |
| 105 | +
|
| 106 | + .compaction-summary__arrow { |
| 107 | + color: var(--clr-text-2); |
| 108 | + } |
| 109 | + } |
| 110 | + } |
| 111 | +
|
| 112 | + .compaction-summary__arrow { |
| 113 | + display: flex; |
| 114 | + color: var(--clr-text-3); |
| 115 | + transition: |
| 116 | +, |
| 117 | + transform var(--transition-medium); |
| 118 | +
|
| 119 | + &.expanded { |
| 120 | + transform: rotate(90deg); |
| 121 | + } |
| 122 | + } |
| 123 | +
|
| 124 | + .compaction-summary__content { |
| 125 | + padding: 12px; |
| 126 | + } |
| 127 | +</style> |
0 commit comments