feat: Deploy template selection, PTY terminal and assistant transcript fixes#68
Conversation
The file manager's Hidden toggle now starts from a setting persisted on the agent instead of always starting off. Hidden files are shown by default and the preference can be changed from the Settings page.
Image and compose deployments can now select an app template. For image deploys the selection prefills the container port and bind mounts while the generated compose keeps the user's image. For both modes the selection is sent with the deployment so the agent prepares directories, environment files and ownership. Compose content written by the user stays untouched. Required mounts are preselected but stay editable in every mode, and the full selection is sent so deselecting a required mount sticks.
Prompts composed by the product when opening the assistant are flagged so the agent excludes them from the visible conversation. Only messages the user types appear in the chat.
The system terminal now speaks the same raw stream protocol as the container terminal, attached to a real PTY on the host. Interactive and terminal-control programs work, keystrokes reach the running program directly, and resizes propagate. Blocked commands are cancelled with a notice instead of returning a synthetic error.
Code Review SummaryThe PR introduces version 0.3.0, featuring PTY terminal support, app template selection during deployment, and improvements to the file manager's hidden file handling. It also refines how assistant transcripts handle seeded messages. 🚀 Key Improvements
💡 Minor Suggestions
|
| const showHiddenFiles = ref(true); | ||
| const hideSystemFolders = ref(true); | ||
|
|
||
| const loadShowHiddenSetting = async () => { |
There was a problem hiding this comment.
The default value of showHiddenFiles is set to true (line 579) but then potentially overwritten by an async call. If the API call is slow, the UI might flicker from showing to hiding hidden files. Consider a loading state or a more robust sync mechanism if this is critical.
| const loadShowHiddenSetting = async () => { | |
| const loadShowHiddenSetting = async () => { | |
| try { | |
| const response = await configApi.get("files.show_hidden"); | |
| const value = response.data.entry?.value; | |
| if (typeof value === "boolean") { | |
| showHiddenFiles.value = value; | |
| } | |
| } catch (err) { | |
| console.debug("Could not load hidden files setting, using default", err); | |
| } | |
| }; |
| @@ -1044,7 +1082,6 @@ | |||
| <input | |||
| type="checkbox" | |||
| :checked="getMountSelection(mount.id)?.enabled" | |||
There was a problem hiding this comment.
The :disabled="mount.required" attribute was removed. While the PR description mentions that required mounts stay editable, ensure the backend/agent can handle a user deselecting a mount that the template identifies as 'required'.
| :checked="getMountSelection(mount.id)?.enabled" | |
| :checked="getMountSelection(mount.id)?.enabled" | |
| @change="toggleMount(mount.id)" |
Deploying flatrun-ui with
|
| Latest commit: |
b826deb
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e9efbf8a.flatrun-ui.pages.dev |
| Branch Preview URL: | https://feat-issue-138-improvements.flatrun-ui.pages.dev |
| if (apiUrl.startsWith("http")) { | ||
| const url = new URL(apiUrl); | ||
| return `${protocol}//${url.host}/api/containers/${props.containerId}/exec`; | ||
| return `${protocol}//${url.host}${path}`; |
There was a problem hiding this comment.
The URL host and path concatenation should ensure that the path starts with a single slash to avoid malformed URLs if path or url.host formatting varies.
| return `${protocol}//${url.host}${path}`; | |
| return `${protocol}//${url.host}${path.startsWith('/') ? '' : '/'}${path}`; |
|
|
||
| const onTemplatePresetChange = () => { | ||
| const app = templatePresetApp.value; | ||
| if (!app) { |
There was a problem hiding this comment.
When switching the template to 'None' (app is null), existing networking ports previously set by a template are not cleared. This might lead to unexpected port configurations if the user switches templates multiple times.
| if (!app) { | |
| if (!app) { | |
| form.mounts = []; | |
| form.networking.ports = [{ containerPort: 80, hostPort: "", expose: true }]; | |
| return; | |
| } |
| generatingCompose.value = true; | ||
| try { | ||
| const enabledMounts = form.mounts.filter((m) => m.enabled); | ||
| const firstPort = form.networking.ports[0] || { containerPort: 80, hostPort: "" }; |
There was a problem hiding this comment.
When generating compose from an image with a template, the container port is hardcoded to 80 if no port is defined. It would be more consistent to use app.container_port as the fallback if available.
| const firstPort = form.networking.ports[0] || { containerPort: 80, hostPort: "" }; | |
| const fallbackPort = templatePresetApp.value?.container_port || 80; | |
| const firstPort = form.networking.ports[0] || { containerPort: fallbackPort, host_port: "" }; |
Summary
Companion agent changes: flatrun/agent#142