feat(ai): Scope file-editor assistant to the deployment and cover env vars#90
Conversation
… vars Asking the assistant from a deployment's file editor now opens a deployment-scoped session, so it can use that deployment's tools and offer one-click actions instead of answering as the whole system. The environment tab gains an assistant button that shares only variable names, never values, since an unsaved draft value cannot be redacted server side.
Code Review SummaryThe PR successfully scopes the file-editor assistant to the deployment context and extends support to environment variables. It also introduces a robust mechanism to reload the editor buffer when the assistant performs file writes. 🚀 Key Improvements
💡 Minor Suggestions
|
| // open file and reload the buffer, unless the operator has unsaved edits. | ||
| const seenAssistWrites = ref(0); | ||
|
|
||
| const assistWritesToOpenFile = (): number => { |
There was a problem hiding this comment.
The logic for parsing tool arguments should account for cases where step.arguments might already be an object (depending on how the store handles the API response). Additionally, scanning the entire session history can be optimized by ensuring JSON.parse isn't called if the result is already known to be irrelevant.
| const assistWritesToOpenFile = (): number => { | |
| const assistWritesToOpenFile = (): number => { | |
| const session = assistStore.session; | |
| const open = (editingFile.value?.path || "").replace(/^\/+/, ""); | |
| if (!session || !open) return 0; | |
| let count = 0; | |
| for (const turn of session.messages) { | |
| for (const step of turn.tool_steps || []) { | |
| if (step.name !== "write_deployment_file" || !step.result || step.result.startsWith("Error")) continue; | |
| try { | |
| const args = typeof step.arguments === 'string' ? JSON.parse(step.arguments || "{}") : step.arguments; | |
| const target = String(args?.path || "").replace(/^\/+/, ""); | |
| if (target && (target === open || open.endsWith("/" + target))) count++; | |
| } catch { | |
| // Unparseable arguments cannot name the open file. | |
| } | |
| } | |
| } | |
| return count; | |
| }; |
|
|
||
| watch(currentPath, () => { |
There was a problem hiding this comment.
When the editor modal is opened, seenAssistWrites starts at 0. If the assistant had already modified this file earlier in the session, the first interaction with the assistant will trigger a redundant reload and notification. It is better to initialize the counter when the file is opened.
| watch(currentPath, () => { | |
| watch(editingFile, (file) => { | |
| if (file) seenAssistWrites.value = assistWritesToOpenFile(); | |
| }, { immediate: true }); | |
| watch(currentPath, () => { |
An assistant write left the open editor buffer stale, so saving afterwards would silently overwrite the assistant's change. The editor now reloads the buffer when an approved write lands on the open file, and warns instead when the operator has unsaved edits.
13f6216 to
ddd4480
Compare
| return count; | ||
| }; | ||
|
|
||
| const reloadEditorContent = async () => { |
There was a problem hiding this comment.
The current implementation of reloadEditorContent is susceptible to race conditions if the user closes the modal or switches files while the fetch is in progress. Additionally, silent failure on fetch error may leave the user confused. This refactored version captures state before the async call and provides an error notification.
| const reloadEditorContent = async () => { | |
| const reloadEditorContent = async () => { | |
| const file = editingFile.value; | |
| if (!file) return; | |
| try { | |
| const response = await fileApi.value.getContent(file.path); | |
| if (!showEditorModal.value || editingFile.value?.path !== file.path) return; | |
| fileContent.value = response.data; | |
| originalContent.value = response.data; | |
| notifications.info("File updated", `${file.name} was reloaded with the assistant's change`); | |
| } catch (error) { | |
| notifications.error("Reload failed", `Could not reload ${file.name} after assistant update.`); | |
| } | |
| }; |
Deploying flatrun-ui with
|
| Latest commit: |
ddd4480
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://e7563545.flatrun-ui.pages.dev |
| Branch Preview URL: | https://feat-file-assist-scope.flatrun-ui.pages.dev |
Closes #71. Most editors already open the assistant with the file as hidden context; this closes the remaining gaps.
The file browser's editor hardcoded a system-scoped session even for a deployment's files, so the assistant answered without that deployment's tools or one-click suggested actions. It now scopes to the deployment when one is set. The environment tab gains an assistant button that shares variable names only, never values: a drafted value is not saved yet, so the server-side redactor cannot know it.
With approval-gated writes, the assistant can edit the open file live. The editor reloads its buffer when an approved write lands on that file, and warns instead of reloading when there are unsaved edits, so a manual save cannot silently overwrite the assistant's change.