@oh-my-pi/pi-web-ui 1.337.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/README.md +609 -0
- package/example/README.md +61 -0
- package/example/index.html +13 -0
- package/example/package.json +24 -0
- package/example/src/app.css +1 -0
- package/example/src/custom-messages.ts +99 -0
- package/example/src/main.ts +420 -0
- package/example/tsconfig.json +23 -0
- package/example/vite.config.ts +6 -0
- package/package.json +57 -0
- package/scripts/count-prompt-tokens.ts +88 -0
- package/src/ChatPanel.ts +218 -0
- package/src/app.css +68 -0
- package/src/components/AgentInterface.ts +390 -0
- package/src/components/AttachmentTile.ts +107 -0
- package/src/components/ConsoleBlock.ts +74 -0
- package/src/components/CustomProviderCard.ts +96 -0
- package/src/components/ExpandableSection.ts +46 -0
- package/src/components/Input.ts +113 -0
- package/src/components/MessageEditor.ts +404 -0
- package/src/components/MessageList.ts +97 -0
- package/src/components/Messages.ts +384 -0
- package/src/components/ProviderKeyInput.ts +152 -0
- package/src/components/SandboxedIframe.ts +626 -0
- package/src/components/StreamingMessageContainer.ts +107 -0
- package/src/components/ThinkingBlock.ts +45 -0
- package/src/components/message-renderer-registry.ts +28 -0
- package/src/components/sandbox/ArtifactsRuntimeProvider.ts +219 -0
- package/src/components/sandbox/AttachmentsRuntimeProvider.ts +66 -0
- package/src/components/sandbox/ConsoleRuntimeProvider.ts +186 -0
- package/src/components/sandbox/FileDownloadRuntimeProvider.ts +110 -0
- package/src/components/sandbox/RuntimeMessageBridge.ts +82 -0
- package/src/components/sandbox/RuntimeMessageRouter.ts +216 -0
- package/src/components/sandbox/SandboxRuntimeProvider.ts +52 -0
- package/src/dialogs/ApiKeyPromptDialog.ts +75 -0
- package/src/dialogs/AttachmentOverlay.ts +640 -0
- package/src/dialogs/CustomProviderDialog.ts +274 -0
- package/src/dialogs/ModelSelector.ts +314 -0
- package/src/dialogs/PersistentStorageDialog.ts +146 -0
- package/src/dialogs/ProvidersModelsTab.ts +212 -0
- package/src/dialogs/SessionListDialog.ts +157 -0
- package/src/dialogs/SettingsDialog.ts +216 -0
- package/src/index.ts +115 -0
- package/src/prompts/prompts.ts +282 -0
- package/src/storage/app-storage.ts +60 -0
- package/src/storage/backends/indexeddb-storage-backend.ts +193 -0
- package/src/storage/store.ts +33 -0
- package/src/storage/stores/custom-providers-store.ts +62 -0
- package/src/storage/stores/provider-keys-store.ts +33 -0
- package/src/storage/stores/sessions-store.ts +136 -0
- package/src/storage/stores/settings-store.ts +34 -0
- package/src/storage/types.ts +206 -0
- package/src/tools/artifacts/ArtifactElement.ts +14 -0
- package/src/tools/artifacts/ArtifactPill.ts +26 -0
- package/src/tools/artifacts/Console.ts +102 -0
- package/src/tools/artifacts/DocxArtifact.ts +213 -0
- package/src/tools/artifacts/ExcelArtifact.ts +231 -0
- package/src/tools/artifacts/GenericArtifact.ts +118 -0
- package/src/tools/artifacts/HtmlArtifact.ts +203 -0
- package/src/tools/artifacts/ImageArtifact.ts +116 -0
- package/src/tools/artifacts/MarkdownArtifact.ts +83 -0
- package/src/tools/artifacts/PdfArtifact.ts +201 -0
- package/src/tools/artifacts/SvgArtifact.ts +82 -0
- package/src/tools/artifacts/TextArtifact.ts +148 -0
- package/src/tools/artifacts/artifacts-tool-renderer.ts +371 -0
- package/src/tools/artifacts/artifacts.ts +713 -0
- package/src/tools/artifacts/index.ts +7 -0
- package/src/tools/extract-document.ts +271 -0
- package/src/tools/index.ts +46 -0
- package/src/tools/javascript-repl.ts +316 -0
- package/src/tools/renderer-registry.ts +127 -0
- package/src/tools/renderers/BashRenderer.ts +52 -0
- package/src/tools/renderers/CalculateRenderer.ts +58 -0
- package/src/tools/renderers/DefaultRenderer.ts +95 -0
- package/src/tools/renderers/GetCurrentTimeRenderer.ts +92 -0
- package/src/tools/types.ts +15 -0
- package/src/utils/attachment-utils.ts +472 -0
- package/src/utils/auth-token.ts +22 -0
- package/src/utils/format.ts +42 -0
- package/src/utils/i18n.ts +653 -0
- package/src/utils/model-discovery.ts +277 -0
- package/src/utils/proxy-utils.ts +134 -0
- package/src/utils/test-sessions.ts +2357 -0
- package/tsconfig.build.json +20 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { CopyButton } from "@mariozechner/mini-lit/dist/CopyButton.js";
|
|
2
|
+
import { DownloadButton } from "@mariozechner/mini-lit/dist/DownloadButton.js";
|
|
3
|
+
import hljs from "highlight.js";
|
|
4
|
+
import { html } from "lit";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
|
+
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
7
|
+
import { i18n } from "../../utils/i18n.js";
|
|
8
|
+
import { ArtifactElement } from "./ArtifactElement.js";
|
|
9
|
+
|
|
10
|
+
// Known code file extensions for highlighting
|
|
11
|
+
const CODE_EXTENSIONS = [
|
|
12
|
+
"js",
|
|
13
|
+
"javascript",
|
|
14
|
+
"ts",
|
|
15
|
+
"typescript",
|
|
16
|
+
"jsx",
|
|
17
|
+
"tsx",
|
|
18
|
+
"py",
|
|
19
|
+
"python",
|
|
20
|
+
"java",
|
|
21
|
+
"c",
|
|
22
|
+
"cpp",
|
|
23
|
+
"cs",
|
|
24
|
+
"php",
|
|
25
|
+
"rb",
|
|
26
|
+
"ruby",
|
|
27
|
+
"go",
|
|
28
|
+
"rust",
|
|
29
|
+
"swift",
|
|
30
|
+
"kotlin",
|
|
31
|
+
"scala",
|
|
32
|
+
"dart",
|
|
33
|
+
"html",
|
|
34
|
+
"css",
|
|
35
|
+
"scss",
|
|
36
|
+
"sass",
|
|
37
|
+
"less",
|
|
38
|
+
"json",
|
|
39
|
+
"xml",
|
|
40
|
+
"yaml",
|
|
41
|
+
"yml",
|
|
42
|
+
"toml",
|
|
43
|
+
"sql",
|
|
44
|
+
"sh",
|
|
45
|
+
"bash",
|
|
46
|
+
"ps1",
|
|
47
|
+
"bat",
|
|
48
|
+
"r",
|
|
49
|
+
"matlab",
|
|
50
|
+
"julia",
|
|
51
|
+
"lua",
|
|
52
|
+
"perl",
|
|
53
|
+
"vue",
|
|
54
|
+
"svelte",
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
@customElement("text-artifact")
|
|
58
|
+
export class TextArtifact extends ArtifactElement {
|
|
59
|
+
@property() override filename = "";
|
|
60
|
+
|
|
61
|
+
private _content = "";
|
|
62
|
+
override get content(): string {
|
|
63
|
+
return this._content;
|
|
64
|
+
}
|
|
65
|
+
override set content(value: string) {
|
|
66
|
+
this._content = value;
|
|
67
|
+
this.requestUpdate();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
71
|
+
return this; // light DOM
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private isCode(): boolean {
|
|
75
|
+
const ext = this.filename.split(".").pop()?.toLowerCase() || "";
|
|
76
|
+
return CODE_EXTENSIONS.includes(ext);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private getLanguageFromExtension(ext: string): string {
|
|
80
|
+
const languageMap: Record<string, string> = {
|
|
81
|
+
js: "javascript",
|
|
82
|
+
ts: "typescript",
|
|
83
|
+
py: "python",
|
|
84
|
+
rb: "ruby",
|
|
85
|
+
yml: "yaml",
|
|
86
|
+
ps1: "powershell",
|
|
87
|
+
bat: "batch",
|
|
88
|
+
};
|
|
89
|
+
return languageMap[ext] || ext;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private getMimeType(): string {
|
|
93
|
+
const ext = this.filename.split(".").pop()?.toLowerCase() || "";
|
|
94
|
+
if (ext === "svg") return "image/svg+xml";
|
|
95
|
+
if (ext === "md" || ext === "markdown") return "text/markdown";
|
|
96
|
+
return "text/plain";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public getHeaderButtons() {
|
|
100
|
+
const copyButton = new CopyButton();
|
|
101
|
+
copyButton.text = this.content;
|
|
102
|
+
copyButton.title = i18n("Copy");
|
|
103
|
+
copyButton.showText = false;
|
|
104
|
+
|
|
105
|
+
return html`
|
|
106
|
+
<div class="flex items-center gap-1">
|
|
107
|
+
${copyButton}
|
|
108
|
+
${DownloadButton({
|
|
109
|
+
content: this.content,
|
|
110
|
+
filename: this.filename,
|
|
111
|
+
mimeType: this.getMimeType(),
|
|
112
|
+
title: i18n("Download"),
|
|
113
|
+
})}
|
|
114
|
+
</div>
|
|
115
|
+
`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
override render() {
|
|
119
|
+
const isCode = this.isCode();
|
|
120
|
+
const ext = this.filename.split(".").pop() || "";
|
|
121
|
+
return html`
|
|
122
|
+
<div class="h-full flex flex-col">
|
|
123
|
+
<div class="flex-1 overflow-auto">
|
|
124
|
+
${
|
|
125
|
+
isCode
|
|
126
|
+
? html`
|
|
127
|
+
<pre class="m-0 p-4 text-xs"><code class="hljs language-${this.getLanguageFromExtension(
|
|
128
|
+
ext.toLowerCase(),
|
|
129
|
+
)}">${unsafeHTML(
|
|
130
|
+
hljs.highlight(this.content, {
|
|
131
|
+
language: this.getLanguageFromExtension(ext.toLowerCase()),
|
|
132
|
+
ignoreIllegals: true,
|
|
133
|
+
}).value,
|
|
134
|
+
)}</code></pre>
|
|
135
|
+
`
|
|
136
|
+
: html` <pre class="m-0 p-4 text-xs font-mono">${this.content}</pre> `
|
|
137
|
+
}
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
declare global {
|
|
145
|
+
interface HTMLElementTagNameMap {
|
|
146
|
+
"text-artifact": TextArtifact;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import "@mariozechner/mini-lit/dist/CodeBlock.js";
|
|
2
|
+
import type { ToolResultMessage } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
4
|
+
import { FileCode2 } from "lucide";
|
|
5
|
+
import "../../components/ConsoleBlock.js";
|
|
6
|
+
import { Diff } from "@mariozechner/mini-lit/dist/Diff.js";
|
|
7
|
+
import { html, type TemplateResult } from "lit";
|
|
8
|
+
import { i18n } from "../../utils/i18n.js";
|
|
9
|
+
import { renderCollapsibleHeader, renderHeader } from "../renderer-registry.js";
|
|
10
|
+
import type { ToolRenderer, ToolRenderResult } from "../types.js";
|
|
11
|
+
import { ArtifactPill } from "./ArtifactPill.js";
|
|
12
|
+
import type { ArtifactsPanel, ArtifactsParams } from "./artifacts.js";
|
|
13
|
+
|
|
14
|
+
// Helper to extract text from content blocks
|
|
15
|
+
function getTextOutput(result: ToolResultMessage<any> | undefined): string {
|
|
16
|
+
if (!result) return "";
|
|
17
|
+
return (
|
|
18
|
+
result.content
|
|
19
|
+
?.filter((c) => c.type === "text")
|
|
20
|
+
.map((c: any) => c.text)
|
|
21
|
+
.join("\n") || ""
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Helper to determine language for syntax highlighting
|
|
26
|
+
function getLanguageFromFilename(filename?: string): string {
|
|
27
|
+
if (!filename) return "text";
|
|
28
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
29
|
+
const languageMap: Record<string, string> = {
|
|
30
|
+
js: "javascript",
|
|
31
|
+
jsx: "javascript",
|
|
32
|
+
ts: "typescript",
|
|
33
|
+
tsx: "typescript",
|
|
34
|
+
html: "html",
|
|
35
|
+
css: "css",
|
|
36
|
+
scss: "scss",
|
|
37
|
+
json: "json",
|
|
38
|
+
py: "python",
|
|
39
|
+
md: "markdown",
|
|
40
|
+
svg: "xml",
|
|
41
|
+
xml: "xml",
|
|
42
|
+
yaml: "yaml",
|
|
43
|
+
yml: "yaml",
|
|
44
|
+
sh: "bash",
|
|
45
|
+
bash: "bash",
|
|
46
|
+
sql: "sql",
|
|
47
|
+
java: "java",
|
|
48
|
+
c: "c",
|
|
49
|
+
cpp: "cpp",
|
|
50
|
+
cs: "csharp",
|
|
51
|
+
go: "go",
|
|
52
|
+
rs: "rust",
|
|
53
|
+
php: "php",
|
|
54
|
+
rb: "ruby",
|
|
55
|
+
swift: "swift",
|
|
56
|
+
kt: "kotlin",
|
|
57
|
+
r: "r",
|
|
58
|
+
};
|
|
59
|
+
return languageMap[ext || ""] || "text";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class ArtifactsToolRenderer implements ToolRenderer<ArtifactsParams, undefined> {
|
|
63
|
+
constructor(public artifactsPanel?: ArtifactsPanel) {}
|
|
64
|
+
|
|
65
|
+
render(
|
|
66
|
+
params: ArtifactsParams | undefined,
|
|
67
|
+
result: ToolResultMessage<undefined> | undefined,
|
|
68
|
+
isStreaming?: boolean,
|
|
69
|
+
): ToolRenderResult {
|
|
70
|
+
const state = result ? (result.isError ? "error" : "complete") : isStreaming ? "inprogress" : "complete";
|
|
71
|
+
|
|
72
|
+
// Create refs for collapsible sections
|
|
73
|
+
const contentRef = createRef<HTMLDivElement>();
|
|
74
|
+
const chevronRef = createRef<HTMLSpanElement>();
|
|
75
|
+
|
|
76
|
+
// Helper to get command labels
|
|
77
|
+
const getCommandLabels = (command: string): { streaming: string; complete: string } => {
|
|
78
|
+
const labels: Record<string, { streaming: string; complete: string }> = {
|
|
79
|
+
create: { streaming: i18n("Creating artifact"), complete: i18n("Created artifact") },
|
|
80
|
+
update: { streaming: i18n("Updating artifact"), complete: i18n("Updated artifact") },
|
|
81
|
+
rewrite: { streaming: i18n("Rewriting artifact"), complete: i18n("Rewrote artifact") },
|
|
82
|
+
get: { streaming: i18n("Getting artifact"), complete: i18n("Got artifact") },
|
|
83
|
+
delete: { streaming: i18n("Deleting artifact"), complete: i18n("Deleted artifact") },
|
|
84
|
+
logs: { streaming: i18n("Getting logs"), complete: i18n("Got logs") },
|
|
85
|
+
};
|
|
86
|
+
return labels[command] || { streaming: i18n("Processing artifact"), complete: i18n("Processed artifact") };
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Helper to render header text with inline artifact pill
|
|
90
|
+
const renderHeaderWithPill = (labelText: string, filename?: string): TemplateResult => {
|
|
91
|
+
if (filename) {
|
|
92
|
+
return html`<span>${labelText} ${ArtifactPill(filename, this.artifactsPanel)}</span>`;
|
|
93
|
+
}
|
|
94
|
+
return html`<span>${labelText}</span>`;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Error handling
|
|
98
|
+
if (result?.isError) {
|
|
99
|
+
const command = params?.command;
|
|
100
|
+
const filename = params?.filename;
|
|
101
|
+
const labels = command
|
|
102
|
+
? getCommandLabels(command)
|
|
103
|
+
: { streaming: i18n("Processing artifact"), complete: i18n("Processed artifact") };
|
|
104
|
+
const headerText = labels.streaming;
|
|
105
|
+
|
|
106
|
+
// For create/update/rewrite errors, show code block + console/error
|
|
107
|
+
if (command === "create" || command === "update" || command === "rewrite") {
|
|
108
|
+
const content = params?.content || "";
|
|
109
|
+
const { old_str, new_str } = params || {};
|
|
110
|
+
const isDiff = command === "update";
|
|
111
|
+
const diffContent =
|
|
112
|
+
old_str !== undefined && new_str !== undefined ? Diff({ oldText: old_str, newText: new_str }) : "";
|
|
113
|
+
|
|
114
|
+
const isHtml = filename?.endsWith(".html");
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
content: html`
|
|
118
|
+
<div>
|
|
119
|
+
${renderCollapsibleHeader(
|
|
120
|
+
state,
|
|
121
|
+
FileCode2,
|
|
122
|
+
renderHeaderWithPill(headerText, filename),
|
|
123
|
+
contentRef,
|
|
124
|
+
chevronRef,
|
|
125
|
+
false,
|
|
126
|
+
)}
|
|
127
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300 space-y-3">
|
|
128
|
+
${
|
|
129
|
+
isDiff
|
|
130
|
+
? diffContent
|
|
131
|
+
: content
|
|
132
|
+
? html`<code-block .code=${content} language=${getLanguageFromFilename(filename)}></code-block>`
|
|
133
|
+
: ""
|
|
134
|
+
}
|
|
135
|
+
${
|
|
136
|
+
isHtml
|
|
137
|
+
? html`<console-block
|
|
138
|
+
.content=${getTextOutput(result) || i18n("An error occurred")}
|
|
139
|
+
variant="error"
|
|
140
|
+
></console-block>`
|
|
141
|
+
: html`<div class="text-sm text-destructive">
|
|
142
|
+
${getTextOutput(result) || i18n("An error occurred")}
|
|
143
|
+
</div>`
|
|
144
|
+
}
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
`,
|
|
148
|
+
isCustom: false,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// For other errors, just show error message
|
|
153
|
+
return {
|
|
154
|
+
content: html`
|
|
155
|
+
<div class="space-y-3">
|
|
156
|
+
${renderHeader(state, FileCode2, headerText)}
|
|
157
|
+
<div class="text-sm text-destructive">${getTextOutput(result) || i18n("An error occurred")}</div>
|
|
158
|
+
</div>
|
|
159
|
+
`,
|
|
160
|
+
isCustom: false,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Full params + result
|
|
165
|
+
if (result && params) {
|
|
166
|
+
const { command, filename, content } = params;
|
|
167
|
+
const labels = command
|
|
168
|
+
? getCommandLabels(command)
|
|
169
|
+
: { streaming: i18n("Processing artifact"), complete: i18n("Processed artifact") };
|
|
170
|
+
const headerText = labels.complete;
|
|
171
|
+
|
|
172
|
+
// GET command: show code block with file content
|
|
173
|
+
if (command === "get") {
|
|
174
|
+
const fileContent = getTextOutput(result) || i18n("(no output)");
|
|
175
|
+
return {
|
|
176
|
+
content: html`
|
|
177
|
+
<div>
|
|
178
|
+
${renderCollapsibleHeader(
|
|
179
|
+
state,
|
|
180
|
+
FileCode2,
|
|
181
|
+
renderHeaderWithPill(headerText, filename),
|
|
182
|
+
contentRef,
|
|
183
|
+
chevronRef,
|
|
184
|
+
false,
|
|
185
|
+
)}
|
|
186
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300">
|
|
187
|
+
<code-block .code=${fileContent} language=${getLanguageFromFilename(filename)}></code-block>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
`,
|
|
191
|
+
isCustom: false,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// LOGS command: show console block
|
|
196
|
+
if (command === "logs") {
|
|
197
|
+
const logs = getTextOutput(result) || i18n("(no output)");
|
|
198
|
+
return {
|
|
199
|
+
content: html`
|
|
200
|
+
<div>
|
|
201
|
+
${renderCollapsibleHeader(
|
|
202
|
+
state,
|
|
203
|
+
FileCode2,
|
|
204
|
+
renderHeaderWithPill(headerText, filename),
|
|
205
|
+
contentRef,
|
|
206
|
+
chevronRef,
|
|
207
|
+
false,
|
|
208
|
+
)}
|
|
209
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300">
|
|
210
|
+
<console-block .content=${logs}></console-block>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
`,
|
|
214
|
+
isCustom: false,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// CREATE/UPDATE/REWRITE: always show code block, + console block for .html files
|
|
219
|
+
if (command === "create" || command === "rewrite") {
|
|
220
|
+
const codeContent = content || "";
|
|
221
|
+
const isHtml = filename?.endsWith(".html");
|
|
222
|
+
const logs = getTextOutput(result) || "";
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
content: html`
|
|
226
|
+
<div>
|
|
227
|
+
${renderCollapsibleHeader(
|
|
228
|
+
state,
|
|
229
|
+
FileCode2,
|
|
230
|
+
renderHeaderWithPill(headerText, filename),
|
|
231
|
+
contentRef,
|
|
232
|
+
chevronRef,
|
|
233
|
+
false,
|
|
234
|
+
)}
|
|
235
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300 space-y-3">
|
|
236
|
+
${
|
|
237
|
+
codeContent
|
|
238
|
+
? html`<code-block .code=${codeContent} language=${getLanguageFromFilename(filename)}></code-block>`
|
|
239
|
+
: ""
|
|
240
|
+
}
|
|
241
|
+
${isHtml && logs ? html`<console-block .content=${logs}></console-block>` : ""}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
`,
|
|
245
|
+
isCustom: false,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (command === "update") {
|
|
250
|
+
const isHtml = filename?.endsWith(".html");
|
|
251
|
+
const logs = getTextOutput(result) || "";
|
|
252
|
+
return {
|
|
253
|
+
content: html`
|
|
254
|
+
<div>
|
|
255
|
+
${renderCollapsibleHeader(
|
|
256
|
+
state,
|
|
257
|
+
FileCode2,
|
|
258
|
+
renderHeaderWithPill(headerText, filename),
|
|
259
|
+
contentRef,
|
|
260
|
+
chevronRef,
|
|
261
|
+
false,
|
|
262
|
+
)}
|
|
263
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300 space-y-3">
|
|
264
|
+
${Diff({ oldText: params.old_str || "", newText: params.new_str || "" })}
|
|
265
|
+
${isHtml && logs ? html`<console-block .content=${logs}></console-block>` : ""}
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
`,
|
|
269
|
+
isCustom: false,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// For DELETE, just show header
|
|
274
|
+
return {
|
|
275
|
+
content: html`
|
|
276
|
+
<div class="space-y-3">${renderHeader(state, FileCode2, renderHeaderWithPill(headerText, filename))}</div>
|
|
277
|
+
`,
|
|
278
|
+
isCustom: false,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Params only (streaming or waiting for result)
|
|
283
|
+
if (params) {
|
|
284
|
+
const { command, filename, content, old_str, new_str } = params;
|
|
285
|
+
|
|
286
|
+
// If no command yet
|
|
287
|
+
if (!command) {
|
|
288
|
+
return { content: renderHeader(state, FileCode2, i18n("Preparing artifact...")), isCustom: false };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const labels = getCommandLabels(command);
|
|
292
|
+
const headerText = labels.streaming;
|
|
293
|
+
|
|
294
|
+
// Render based on command type
|
|
295
|
+
switch (command) {
|
|
296
|
+
case "create":
|
|
297
|
+
case "rewrite":
|
|
298
|
+
return {
|
|
299
|
+
content: html`
|
|
300
|
+
<div>
|
|
301
|
+
${renderCollapsibleHeader(
|
|
302
|
+
state,
|
|
303
|
+
FileCode2,
|
|
304
|
+
renderHeaderWithPill(headerText, filename),
|
|
305
|
+
contentRef,
|
|
306
|
+
chevronRef,
|
|
307
|
+
false,
|
|
308
|
+
)}
|
|
309
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300">
|
|
310
|
+
${
|
|
311
|
+
content
|
|
312
|
+
? html`<code-block .code=${content} language=${getLanguageFromFilename(filename)}></code-block>`
|
|
313
|
+
: ""
|
|
314
|
+
}
|
|
315
|
+
</div>
|
|
316
|
+
</div>
|
|
317
|
+
`,
|
|
318
|
+
isCustom: false,
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
case "update":
|
|
322
|
+
return {
|
|
323
|
+
content: html`
|
|
324
|
+
<div>
|
|
325
|
+
${renderCollapsibleHeader(
|
|
326
|
+
state,
|
|
327
|
+
FileCode2,
|
|
328
|
+
renderHeaderWithPill(headerText, filename),
|
|
329
|
+
contentRef,
|
|
330
|
+
chevronRef,
|
|
331
|
+
false,
|
|
332
|
+
)}
|
|
333
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300">
|
|
334
|
+
${old_str !== undefined && new_str !== undefined ? Diff({ oldText: old_str, newText: new_str }) : ""}
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
`,
|
|
338
|
+
isCustom: false,
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
case "get":
|
|
342
|
+
case "logs":
|
|
343
|
+
return {
|
|
344
|
+
content: html`
|
|
345
|
+
<div>
|
|
346
|
+
${renderCollapsibleHeader(
|
|
347
|
+
state,
|
|
348
|
+
FileCode2,
|
|
349
|
+
renderHeaderWithPill(headerText, filename),
|
|
350
|
+
contentRef,
|
|
351
|
+
chevronRef,
|
|
352
|
+
false,
|
|
353
|
+
)}
|
|
354
|
+
<div ${ref(contentRef)} class="max-h-0 overflow-hidden transition-all duration-300"></div>
|
|
355
|
+
</div>
|
|
356
|
+
`,
|
|
357
|
+
isCustom: false,
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
default:
|
|
361
|
+
return {
|
|
362
|
+
content: html` <div>${renderHeader(state, FileCode2, renderHeaderWithPill(headerText, filename))}</div> `,
|
|
363
|
+
isCustom: false,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// No params or result yet
|
|
369
|
+
return { content: renderHeader(state, FileCode2, i18n("Preparing artifact...")), isCustom: false };
|
|
370
|
+
}
|
|
371
|
+
}
|