blob: e4c580201febd656f889090220dd0d895b607b0d [file] [log] [blame]
Sean McCullough86b56862025-04-18 13:04:03 -07001import { State } from "../types";
Sean McCulloughb29f8912025-04-20 15:39:11 -07002import { LitElement, css, html } from "lit";
3import { customElement, property } from "lit/decorators.js";
Sean McCullough86b56862025-04-18 13:04:03 -07004
5@customElement("sketch-container-status")
6export class SketchContainerStatus extends LitElement {
7 // Header bar: Container status details
8
9 @property()
10 state: State;
11
12 // See https://lit.dev/docs/components/styles/ for how lit-element handles CSS.
13 // Note that these styles only apply to the scope of this web component's
14 // shadow DOM node, so they won't leak out or collide with CSS declared in
15 // other components or the containing web page (...unless you want it to do that).
16 static styles = css`
17 .info-card {
18 background: #f9f9f9;
19 border-radius: 8px;
20 padding: 15px;
21 margin-bottom: 20px;
22 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
23 display: none; /* Hidden in the combined layout */
24 }
25
26 .info-grid {
27 display: flex;
28 flex-wrap: wrap;
29 gap: 8px;
30 background: #f9f9f9;
31 border-radius: 4px;
32 padding: 4px 10px;
33 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
34 flex: 1;
35 }
36
37 .info-item {
38 display: flex;
39 align-items: center;
40 white-space: nowrap;
41 margin-right: 10px;
42 font-size: 13px;
43 }
44
45 .info-label {
46 font-size: 11px;
47 color: #555;
48 margin-right: 3px;
49 font-weight: 500;
50 }
51
52 .info-value {
53 font-size: 11px;
54 font-weight: 600;
55 }
56
57 .cost {
58 color: #2e7d32;
59 }
60
61 .info-item a {
62 --tw-text-opacity: 1;
63 color: rgb(37 99 235 / var(--tw-text-opacity, 1));
64 text-decoration: inherit;
65 }
66 `;
67
68 constructor() {
69 super();
70 }
71
72 // See https://lit.dev/docs/components/lifecycle/
73 connectedCallback() {
74 super.connectedCallback();
75 // register event listeners
76 }
77
78 // See https://lit.dev/docs/components/lifecycle/
79 disconnectedCallback() {
80 super.disconnectedCallback();
81 // unregister event listeners
82 }
83
84 render() {
85 return html`
86 <div class="info-grid">
87 <div class="info-item">
88 <a href="logs">Logs</a>
89 </div>
90 <div class="info-item">
91 <a href="download">Download</a>
92 </div>
93 <div class="info-item">
94 <span id="hostname" class="info-value">${this.state?.hostname}</span>
95 </div>
96 <div class="info-item">
97 <span id="workingDir" class="info-value"
98 >${this.state?.working_dir}</span
99 >
100 </div>
101 <div class="info-item">
102 <span class="info-label">Commit:</span>
103 <span id="initialCommit" class="info-value"
104 >${this.state?.initial_commit?.substring(0, 8)}</span
105 >
106 </div>
107 <div class="info-item">
108 <span class="info-label">Msgs:</span>
109 <span id="messageCount" class="info-value"
110 >${this.state?.message_count}</span
111 >
112 </div>
113 <div class="info-item">
114 <span class="info-label">In:</span>
115 <span id="inputTokens" class="info-value"
116 >${this.state?.total_usage?.input_tokens}</span
117 >
118 </div>
119 <div class="info-item">
120 <span class="info-label">Cache Read:</span>
121 <span id="cacheReadInputTokens" class="info-value"
122 >${this.state?.total_usage?.cache_read_input_tokens}</span
123 >
124 </div>
125 <div class="info-item">
126 <span class="info-label">Cache Create:</span>
127 <span id="cacheCreationInputTokens" class="info-value"
128 >${this.state?.total_usage?.cache_creation_input_tokens}</span
129 >
130 </div>
131 <div class="info-item">
132 <span class="info-label">Out:</span>
133 <span id="outputTokens" class="info-value"
134 >${this.state?.total_usage?.output_tokens}</span
135 >
136 </div>
137 <div class="info-item">
138 <span class="info-label">Cost:</span>
Sean McCullough71941bd2025-04-18 13:31:48 -0700139 <span id="totalCost" class="info-value cost"
140 >$${(this.state?.total_usage?.total_cost_usd || 0).toFixed(2)}</span
141 >
Sean McCullough86b56862025-04-18 13:04:03 -0700142 </div>
143 </div>
144 `;
145 }
146}
147
148declare global {
149 interface HTMLElementTagNameMap {
150 "sketch-container-status": SketchContainerStatus;
151 }
152}