mirror of
https://github.com/JohnRiceML/clawport-ui.git
synced 2026-08-14 00:47:50 +00:00
fix: lazy OpenAI client + canonical workspace detection from openclaw.json
Move OpenAI client initialization from module top-level to a lazy singleton (lib/openai.ts) called inside route handlers. Prevents build errors when gateway env vars aren't set. Also adds openclaw.json agents.defaults.workspace as the first workspace detection source, before falling back to filesystem paths. Inspired by PR #21 (cherry-picked the good parts, skipped the fragile cli-utils rewrite and the agents-registry simplification that dropped sub-agents). Bumps to v0.8.8. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
602e9cd56d
commit
a51ac3cbe0
@@ -3,14 +3,8 @@ export const runtime = 'nodejs'
|
||||
import { getAgent } from '@/lib/agents'
|
||||
import { validateChatMessages } from '@/lib/validation'
|
||||
import { hasImageContent, extractImageAttachments, buildTextPrompt, sendViaOpenClaw } from '@/lib/anthropic'
|
||||
import OpenAI from 'openai'
|
||||
import { gatewayBaseUrl } from '@/lib/env'
|
||||
|
||||
// Route through the OpenClaw gateway — no separate API key needed
|
||||
const openai = new OpenAI({
|
||||
baseURL: gatewayBaseUrl(),
|
||||
apiKey: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
})
|
||||
import { getOpenAIClient } from '@/lib/openai'
|
||||
import type OpenAI from 'openai'
|
||||
|
||||
const GATEWAY_TOKEN = process.env.OPENCLAW_GATEWAY_TOKEN || ''
|
||||
|
||||
@@ -18,6 +12,7 @@ export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const openai = getOpenAIClient()
|
||||
const { id } = await params
|
||||
const agent = await getAgent(id)
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
import { getAgent } from '@/lib/agents'
|
||||
import OpenAI from 'openai'
|
||||
import { gatewayBaseUrl } from '@/lib/env'
|
||||
|
||||
const openai = new OpenAI({
|
||||
baseURL: gatewayBaseUrl(),
|
||||
apiKey: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
})
|
||||
import { getOpenAIClient } from '@/lib/openai'
|
||||
import type OpenAI from 'openai'
|
||||
|
||||
const MAX_TITLE = 500
|
||||
const MAX_DESC = 5000
|
||||
@@ -27,6 +22,7 @@ export async function POST(
|
||||
request: Request,
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
const openai = getOpenAIClient()
|
||||
const { id } = await params
|
||||
const agent = await getAgent(id)
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
import OpenAI from 'openai'
|
||||
import { gatewayBaseUrl } from '@/lib/env'
|
||||
|
||||
const openai = new OpenAI({
|
||||
baseURL: gatewayBaseUrl(),
|
||||
apiKey: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
})
|
||||
import { getOpenAIClient } from '@/lib/openai'
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const openai = getOpenAIClient()
|
||||
let formData: FormData
|
||||
try {
|
||||
formData = await request.formData()
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
import OpenAI from 'openai'
|
||||
import { gatewayBaseUrl } from '@/lib/env'
|
||||
|
||||
const openai = new OpenAI({
|
||||
baseURL: gatewayBaseUrl(),
|
||||
apiKey: process.env.OPENCLAW_GATEWAY_TOKEN,
|
||||
})
|
||||
import { getOpenAIClient } from '@/lib/openai'
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const openai = getOpenAIClient()
|
||||
try {
|
||||
const { text, voice } = await request.json()
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import OpenAI from 'openai'
|
||||
import { gatewayBaseUrl } from './env'
|
||||
|
||||
/**
|
||||
* Lazy-initialized OpenAI client routed through the OpenClaw gateway.
|
||||
*
|
||||
* Call inside route handlers, not at module top level, so builds don't
|
||||
* fail when environment variables aren't set.
|
||||
*/
|
||||
let _openai: OpenAI | null = null
|
||||
|
||||
export function getOpenAIClient(): OpenAI {
|
||||
if (!_openai) {
|
||||
_openai = new OpenAI({
|
||||
baseURL: gatewayBaseUrl(),
|
||||
apiKey: process.env.OPENCLAW_GATEWAY_TOKEN || '',
|
||||
})
|
||||
}
|
||||
return _openai
|
||||
}
|
||||
+18
-5
@@ -21,15 +21,28 @@ import { execSync } from 'child_process'
|
||||
* Detect the default workspace path.
|
||||
*
|
||||
* Checks in order:
|
||||
* 1. ~/.openclaw/agents/main/workspace (current agent-scoped layout)
|
||||
* 2. ~/.openclaw/workspace-main (multi-agent layout, main agent)
|
||||
* 3. ~/.openclaw/workspace-* (multi-agent layout, any agent)
|
||||
* 4. ~/.openclaw/workspace (legacy single-workspace layout)
|
||||
* 1. ~/.openclaw/openclaw.json agents.defaults.workspace (canonical)
|
||||
* 2. ~/.openclaw/agents/main/workspace (current agent-scoped layout)
|
||||
* 3. ~/.openclaw/workspace-main (multi-agent layout, main agent)
|
||||
* 4. ~/.openclaw/workspace-* (multi-agent layout, any agent)
|
||||
* 5. ~/.openclaw/workspace (legacy single-workspace layout)
|
||||
*/
|
||||
export function detectWorkspacePath(): string | null {
|
||||
const base = join(homedir(), '.openclaw')
|
||||
|
||||
// 1. Current agent-scoped layout
|
||||
// 1. Read from openclaw.json (canonical source)
|
||||
const configPath = join(base, 'openclaw.json')
|
||||
if (existsSync(configPath)) {
|
||||
try {
|
||||
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
|
||||
const ws = config?.agents?.defaults?.workspace
|
||||
if (typeof ws === 'string' && existsSync(ws)) return ws
|
||||
} catch {
|
||||
// Invalid JSON, fall through
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Current agent-scoped layout
|
||||
const agentPath = join(base, 'agents', 'main', 'workspace')
|
||||
if (existsSync(agentPath)) return agentPath
|
||||
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "clawport-ui",
|
||||
"version": "0.8.7",
|
||||
"version": "0.8.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "clawport-ui",
|
||||
"version": "0.8.7",
|
||||
"version": "0.8.8",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@dagrejs/dagre": "^2.0.4",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clawport-ui",
|
||||
"version": "0.8.7",
|
||||
"version": "0.8.8",
|
||||
"description": "Open-source dashboard for managing, monitoring, and chatting with your OpenClaw AI agents.",
|
||||
"homepage": "https://clawport.dev",
|
||||
"repository": {
|
||||
|
||||
+13
-1
@@ -45,7 +45,19 @@ function exec(cmd) {
|
||||
function detectWorkspacePath() {
|
||||
const base = join(homedir(), '.openclaw')
|
||||
|
||||
// 1. Current agent-scoped layout
|
||||
// 1. Read from openclaw.json (canonical source)
|
||||
const configPath = join(base, 'openclaw.json')
|
||||
if (existsSync(configPath)) {
|
||||
try {
|
||||
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
|
||||
const ws = config?.agents?.defaults?.workspace
|
||||
if (typeof ws === 'string' && existsSync(ws)) return ws
|
||||
} catch {
|
||||
// Invalid JSON, fall through
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Current agent-scoped layout
|
||||
const agentPath = join(base, 'agents', 'main', 'workspace')
|
||||
if (existsSync(agentPath)) return agentPath
|
||||
|
||||
|
||||
Reference in New Issue
Block a user