Remember last used binary and show environment variables
This commit is contained in:
@@ -57,15 +57,29 @@ class ProcessManager {
|
|||||||
environmentVariables?: Record<string, string>,
|
environmentVariables?: Record<string, string>,
|
||||||
): Promise<ProcessInfo> {
|
): Promise<ProcessInfo> {
|
||||||
this.validateFolder(folder)
|
this.validateFolder(folder)
|
||||||
const actualBinaryPath = binaryPath ? this.validateCustomBinary(binaryPath) : this.validateOpenCodeBinary()
|
const actualBinaryPath =
|
||||||
|
binaryPath && binaryPath !== "opencode" ? this.validateCustomBinary(binaryPath) : this.validateOpenCodeBinary()
|
||||||
|
|
||||||
this.sendLog(instanceId, "info", `Starting OpenCode server for ${folder} using ${actualBinaryPath}...`)
|
this.sendLog(
|
||||||
|
instanceId,
|
||||||
|
"info",
|
||||||
|
`Starting OpenCode server for ${folder} using ${binaryPath || "opencode"} (${actualBinaryPath})...`,
|
||||||
|
)
|
||||||
|
|
||||||
// Merge environment variables with process environment
|
// Merge environment variables with process environment
|
||||||
const env = { ...process.env }
|
const env = { ...process.env }
|
||||||
if (environmentVariables) {
|
if (environmentVariables) {
|
||||||
Object.assign(env, environmentVariables)
|
Object.assign(env, environmentVariables)
|
||||||
this.sendLog(instanceId, "info", `Using ${Object.keys(environmentVariables).length} custom environment variables`)
|
this.sendLog(
|
||||||
|
instanceId,
|
||||||
|
"info",
|
||||||
|
`Using ${Object.keys(environmentVariables).length} custom environment variables:`,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Log each environment variable
|
||||||
|
for (const [key, value] of Object.entries(environmentVariables)) {
|
||||||
|
this.sendLog(instanceId, "info", ` ${key}=${value}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Component, createSignal, Show, For, onMount, onCleanup } from "solid-js"
|
import { Component, createSignal, Show, For, onMount, onCleanup, createEffect } from "solid-js"
|
||||||
import { Folder, Clock, Trash2, FolderPlus, Settings, ChevronDown, ChevronUp } from "lucide-solid"
|
import { Folder, Clock, Trash2, FolderPlus, Settings, ChevronDown, ChevronUp } from "lucide-solid"
|
||||||
import { recentFolders, removeRecentFolder, preferences } from "../stores/preferences"
|
import { recentFolders, removeRecentFolder, preferences, updateLastUsedBinary } from "../stores/preferences"
|
||||||
import OpenCodeBinarySelector from "./opencode-binary-selector"
|
import OpenCodeBinarySelector from "./opencode-binary-selector"
|
||||||
import EnvironmentVariablesEditor from "./environment-variables-editor"
|
import EnvironmentVariablesEditor from "./environment-variables-editor"
|
||||||
|
|
||||||
@@ -17,6 +17,14 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
|||||||
|
|
||||||
const folders = () => recentFolders()
|
const folders = () => recentFolders()
|
||||||
|
|
||||||
|
// Update selected binary when preferences change
|
||||||
|
createEffect(() => {
|
||||||
|
const lastUsed = preferences().lastUsedBinary
|
||||||
|
if (lastUsed && lastUsed !== selectedBinary()) {
|
||||||
|
setSelectedBinary(lastUsed)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
function scrollToIndex(index: number) {
|
function scrollToIndex(index: number) {
|
||||||
const element = document.querySelector(`[data-folder-index="${index}"]`)
|
const element = document.querySelector(`[data-folder-index="${index}"]`)
|
||||||
if (element) {
|
if (element) {
|
||||||
@@ -115,13 +123,19 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleFolderSelect(path: string) {
|
function handleFolderSelect(path: string) {
|
||||||
|
updateLastUsedBinary(selectedBinary())
|
||||||
props.onSelectFolder(path, selectedBinary())
|
props.onSelectFolder(path, selectedBinary())
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBrowse() {
|
function handleBrowse() {
|
||||||
|
updateLastUsedBinary(selectedBinary())
|
||||||
props.onSelectFolder(undefined, selectedBinary())
|
props.onSelectFolder(undefined, selectedBinary())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleBinaryChange(binary: string) {
|
||||||
|
setSelectedBinary(binary)
|
||||||
|
}
|
||||||
|
|
||||||
function handleRemove(path: string, e?: Event) {
|
function handleRemove(path: string, e?: Event) {
|
||||||
e?.stopPropagation()
|
e?.stopPropagation()
|
||||||
removeRecentFolder(path)
|
removeRecentFolder(path)
|
||||||
@@ -271,7 +285,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
|||||||
<div class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">OpenCode Binary</div>
|
<div class="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">OpenCode Binary</div>
|
||||||
<OpenCodeBinarySelector
|
<OpenCodeBinarySelector
|
||||||
selectedBinary={selectedBinary()}
|
selectedBinary={selectedBinary()}
|
||||||
onBinaryChange={setSelectedBinary}
|
onBinaryChange={handleBinaryChange}
|
||||||
disabled={props.isLoading}
|
disabled={props.isLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -142,6 +142,28 @@ const InstanceInfo: Component<InstanceInfoProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
<Show when={props.instance.environmentVariables && Object.keys(props.instance.environmentVariables).length > 0}>
|
||||||
|
<div>
|
||||||
|
<div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1.5">
|
||||||
|
Environment Variables ({Object.keys(props.instance.environmentVariables!).length})
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1">
|
||||||
|
<For each={Object.entries(props.instance.environmentVariables!)}>
|
||||||
|
{([key, value]) => (
|
||||||
|
<div class="flex items-center gap-2 px-2 py-1.5 bg-gray-50 dark:bg-gray-900 rounded border border-gray-200 dark:border-gray-700">
|
||||||
|
<span class="text-xs text-gray-900 dark:text-gray-100 font-mono font-medium flex-1" title={key}>
|
||||||
|
{key}
|
||||||
|
</span>
|
||||||
|
<span class="text-xs text-gray-600 dark:text-gray-400 font-mono flex-1" title={value}>
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<Show when={!isLoadingMetadata() && mcpServers().length > 0}>
|
<Show when={!isLoadingMetadata() && mcpServers().length > 0}>
|
||||||
<div>
|
<div>
|
||||||
<div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1.5">
|
<div class="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1.5">
|
||||||
|
|||||||
@@ -82,6 +82,27 @@ const LogsView: Component<LogsViewProps> = (props) => {
|
|||||||
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300">Server Logs</h3>
|
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300">Server Logs</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Show when={instance()?.environmentVariables && Object.keys(instance()?.environmentVariables!).length > 0}>
|
||||||
|
<div class="px-4 py-3 bg-blue-50 dark:bg-blue-900/20 border-b border-blue-200 dark:border-blue-800">
|
||||||
|
<div class="text-xs font-medium text-blue-800 dark:text-blue-200 mb-2">
|
||||||
|
Environment Variables ({Object.keys(instance()?.environmentVariables!).length})
|
||||||
|
</div>
|
||||||
|
<div class="space-y-1">
|
||||||
|
<For each={Object.entries(instance()?.environmentVariables!)}>
|
||||||
|
{([key, value]) => (
|
||||||
|
<div class="flex items-center gap-2 text-xs">
|
||||||
|
<span class="font-mono font-medium text-blue-800 dark:text-blue-200 min-w-0 flex-1">{key}</span>
|
||||||
|
<span class="text-blue-600 dark:text-blue-400">=</span>
|
||||||
|
<span class="font-mono text-blue-700 dark:text-blue-300 min-w-0 flex-1" title={value}>
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { Instance, LogEntry } from "../types/instance"
|
|||||||
import { sdkManager } from "../lib/sdk-manager"
|
import { sdkManager } from "../lib/sdk-manager"
|
||||||
import { sseManager } from "../lib/sse-manager"
|
import { sseManager } from "../lib/sse-manager"
|
||||||
import { fetchSessions, fetchAgents, fetchProviders } from "./sessions"
|
import { fetchSessions, fetchAgents, fetchProviders } from "./sessions"
|
||||||
import { preferences } from "./preferences"
|
import { preferences, updateLastUsedBinary } from "./preferences"
|
||||||
|
|
||||||
const [instances, setInstances] = createSignal<Map<string, Instance>>(new Map())
|
const [instances, setInstances] = createSignal<Map<string, Instance>>(new Map())
|
||||||
const [activeInstanceId, setActiveInstanceId] = createSignal<string | null>(null)
|
const [activeInstanceId, setActiveInstanceId] = createSignal<string | null>(null)
|
||||||
@@ -52,10 +52,16 @@ async function createInstance(folder: string, binaryPath?: string): Promise<stri
|
|||||||
status: "starting",
|
status: "starting",
|
||||||
client: null,
|
client: null,
|
||||||
logs: [],
|
logs: [],
|
||||||
|
environmentVariables: preferences().environmentVariables,
|
||||||
}
|
}
|
||||||
|
|
||||||
addInstance(instance)
|
addInstance(instance)
|
||||||
|
|
||||||
|
// Update last used binary
|
||||||
|
if (binaryPath) {
|
||||||
|
updateLastUsedBinary(binaryPath)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {
|
const {
|
||||||
id: returnedId,
|
id: returnedId,
|
||||||
|
|||||||
@@ -96,8 +96,13 @@ function updateLastUsedBinary(path: string): void {
|
|||||||
updatePreferences({ lastUsedBinary: path })
|
updatePreferences({ lastUsedBinary: path })
|
||||||
|
|
||||||
const binaries = opencodeBinaries()
|
const binaries = opencodeBinaries()
|
||||||
const binary = binaries.find((b) => b.path === path)
|
let binary = binaries.find((b) => b.path === path)
|
||||||
if (binary) {
|
|
||||||
|
// If binary not found in list, add it (for system PATH "opencode")
|
||||||
|
if (!binary) {
|
||||||
|
addOpenCodeBinary(path)
|
||||||
|
binary = { path, lastUsed: Date.now() }
|
||||||
|
} else {
|
||||||
binary.lastUsed = Date.now()
|
binary.lastUsed = Date.now()
|
||||||
// Move to front
|
// Move to front
|
||||||
const sorted = [binary, ...binaries.filter((b) => b.path !== path)]
|
const sorted = [binary, ...binaries.filter((b) => b.path !== path)]
|
||||||
|
|||||||
@@ -38,4 +38,5 @@ export interface Instance {
|
|||||||
logs: LogEntry[]
|
logs: LogEntry[]
|
||||||
metadata?: InstanceMetadata
|
metadata?: InstanceMetadata
|
||||||
binaryPath?: string
|
binaryPath?: string
|
||||||
|
environmentVariables?: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user