@swarmclawai/swarmclaw 0.4.0 → 0.4.5
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/README.md +13 -2
- package/next.config.ts +8 -0
- package/package.json +2 -1
- package/src/app/api/agents/[id]/route.ts +20 -21
- package/src/app/api/agents/[id]/thread/route.ts +2 -2
- package/src/app/api/agents/route.ts +3 -2
- package/src/app/api/clawhub/install/route.ts +2 -2
- package/src/app/api/connectors/[id]/route.ts +10 -3
- package/src/app/api/connectors/[id]/webhook/route.ts +99 -0
- package/src/app/api/connectors/route.ts +6 -3
- package/src/app/api/credentials/[id]/route.ts +2 -1
- package/src/app/api/credentials/route.ts +2 -2
- package/src/app/api/documents/route.ts +2 -2
- package/src/app/api/files/serve/route.ts +8 -0
- package/src/app/api/knowledge/[id]/route.ts +5 -4
- package/src/app/api/knowledge/upload/route.ts +2 -2
- package/src/app/api/mcp-servers/[id]/route.ts +11 -14
- package/src/app/api/mcp-servers/[id]/test/route.ts +2 -1
- package/src/app/api/mcp-servers/[id]/tools/route.ts +2 -1
- package/src/app/api/mcp-servers/route.ts +2 -2
- package/src/app/api/memory/[id]/route.ts +9 -8
- package/src/app/api/memory/route.ts +2 -2
- package/src/app/api/memory-images/[filename]/route.ts +2 -1
- package/src/app/api/openclaw/directory/route.ts +26 -0
- package/src/app/api/openclaw/discover/route.ts +61 -0
- package/src/app/api/openclaw/sync/route.ts +30 -0
- package/src/app/api/orchestrator/run/route.ts +2 -2
- package/src/app/api/projects/[id]/route.ts +55 -0
- package/src/app/api/projects/route.ts +27 -0
- package/src/app/api/providers/[id]/models/route.ts +2 -1
- package/src/app/api/providers/[id]/route.ts +13 -15
- package/src/app/api/providers/route.ts +2 -2
- package/src/app/api/schedules/[id]/route.ts +16 -18
- package/src/app/api/schedules/[id]/run/route.ts +4 -3
- package/src/app/api/schedules/route.ts +2 -2
- package/src/app/api/secrets/[id]/route.ts +16 -17
- package/src/app/api/secrets/route.ts +2 -2
- package/src/app/api/sessions/[id]/clear/route.ts +2 -1
- package/src/app/api/sessions/[id]/deploy/route.ts +2 -1
- package/src/app/api/sessions/[id]/devserver/route.ts +2 -1
- package/src/app/api/sessions/[id]/messages/route.ts +2 -1
- package/src/app/api/sessions/[id]/retry/route.ts +2 -1
- package/src/app/api/sessions/[id]/route.ts +2 -1
- package/src/app/api/sessions/route.ts +2 -2
- package/src/app/api/skills/[id]/route.ts +23 -21
- package/src/app/api/skills/import/route.ts +2 -2
- package/src/app/api/skills/route.ts +2 -2
- package/src/app/api/tasks/[id]/approve/route.ts +2 -1
- package/src/app/api/tasks/[id]/route.ts +6 -5
- package/src/app/api/tasks/route.ts +2 -2
- package/src/app/api/tts/stream/route.ts +48 -0
- package/src/app/api/upload/route.ts +2 -2
- package/src/app/api/uploads/[filename]/route.ts +4 -1
- package/src/app/api/webhooks/[id]/route.ts +29 -31
- package/src/app/api/webhooks/route.ts +2 -2
- package/src/app/page.tsx +3 -24
- package/src/cli/index.js +28 -0
- package/src/cli/index.ts +1 -1
- package/src/cli/spec.js +2 -0
- package/src/components/agents/agent-list.tsx +3 -1
- package/src/components/agents/agent-sheet.tsx +116 -14
- package/src/components/chat/chat-area.tsx +27 -4
- package/src/components/chat/chat-header.tsx +141 -29
- package/src/components/chat/tool-call-bubble.tsx +9 -3
- package/src/components/chat/voice-overlay.tsx +80 -0
- package/src/components/connectors/connector-list.tsx +6 -2
- package/src/components/connectors/connector-sheet.tsx +31 -7
- package/src/components/layout/app-layout.tsx +47 -25
- package/src/components/projects/project-list.tsx +122 -0
- package/src/components/projects/project-sheet.tsx +135 -0
- package/src/components/schedules/schedule-list.tsx +3 -1
- package/src/components/sessions/new-session-sheet.tsx +6 -6
- package/src/components/sessions/session-card.tsx +1 -1
- package/src/components/sessions/session-list.tsx +7 -7
- package/src/components/shared/connector-platform-icon.tsx +4 -0
- package/src/components/shared/settings/section-heartbeat.tsx +1 -1
- package/src/components/shared/settings/section-orchestrator.tsx +1 -2
- package/src/components/shared/settings/section-web-search.tsx +56 -0
- package/src/components/shared/settings/settings-page.tsx +73 -0
- package/src/components/skills/skill-list.tsx +2 -1
- package/src/components/tasks/task-list.tsx +5 -2
- package/src/hooks/use-continuous-speech.ts +144 -0
- package/src/hooks/use-view-router.ts +52 -0
- package/src/hooks/use-voice-conversation.ts +80 -0
- package/src/lib/id.ts +6 -0
- package/src/lib/projects.ts +13 -0
- package/src/lib/provider-sets.ts +5 -0
- package/src/lib/providers/anthropic.ts +14 -1
- package/src/lib/providers/index.ts +6 -0
- package/src/lib/providers/ollama.ts +9 -1
- package/src/lib/providers/openai.ts +9 -1
- package/src/lib/providers/openclaw.ts +11 -0
- package/src/lib/server/api-routes.test.ts +5 -6
- package/src/lib/server/build-llm.ts +17 -4
- package/src/lib/server/chat-execution.ts +38 -4
- package/src/lib/server/collection-helpers.ts +54 -0
- package/src/lib/server/connectors/bluebubbles.test.ts +208 -0
- package/src/lib/server/connectors/bluebubbles.ts +357 -0
- package/src/lib/server/connectors/connector-routing.test.ts +1 -1
- package/src/lib/server/connectors/googlechat.ts +46 -7
- package/src/lib/server/connectors/manager.ts +392 -3
- package/src/lib/server/connectors/media.ts +2 -2
- package/src/lib/server/connectors/openclaw.ts +64 -0
- package/src/lib/server/connectors/pairing.test.ts +99 -0
- package/src/lib/server/connectors/pairing.ts +256 -0
- package/src/lib/server/connectors/signal.ts +1 -0
- package/src/lib/server/connectors/teams.ts +5 -5
- package/src/lib/server/connectors/types.ts +10 -0
- package/src/lib/server/execution-log.ts +3 -3
- package/src/lib/server/heartbeat-service.ts +1 -1
- package/src/lib/server/knowledge-db.test.ts +2 -33
- package/src/lib/server/main-agent-loop.ts +6 -6
- package/src/lib/server/memory-db.ts +6 -6
- package/src/lib/server/openclaw-approvals.ts +105 -0
- package/src/lib/server/openclaw-sync.ts +496 -0
- package/src/lib/server/orchestrator-lg.ts +30 -9
- package/src/lib/server/orchestrator.ts +4 -4
- package/src/lib/server/process-manager.ts +2 -2
- package/src/lib/server/queue.ts +22 -10
- package/src/lib/server/scheduler.ts +2 -2
- package/src/lib/server/session-mailbox.ts +2 -2
- package/src/lib/server/session-run-manager.ts +2 -2
- package/src/lib/server/session-tools/connector.ts +51 -4
- package/src/lib/server/session-tools/crud.ts +3 -3
- package/src/lib/server/session-tools/delegate.ts +3 -3
- package/src/lib/server/session-tools/file.ts +176 -3
- package/src/lib/server/session-tools/index.ts +2 -0
- package/src/lib/server/session-tools/memory.ts +2 -2
- package/src/lib/server/session-tools/openclaw-nodes.ts +112 -0
- package/src/lib/server/session-tools/sandbox.ts +33 -0
- package/src/lib/server/session-tools/search-providers.ts +270 -0
- package/src/lib/server/session-tools/session-info.ts +2 -2
- package/src/lib/server/session-tools/web.ts +47 -66
- package/src/lib/server/storage.ts +12 -0
- package/src/lib/server/stream-agent-chat.ts +29 -0
- package/src/lib/server/task-result.test.ts +44 -0
- package/src/lib/server/task-result.ts +14 -0
- package/src/lib/tool-definitions.ts +5 -3
- package/src/lib/tts-stream.ts +130 -0
- package/src/lib/view-routes.ts +28 -0
- package/src/proxy.ts +3 -0
- package/src/stores/use-app-store.ts +28 -1
- package/src/stores/use-chat-store.ts +9 -1
- package/src/types/index.ts +27 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { genId } from '@/lib/id'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import { NextResponse } from 'next/server'
|
|
4
4
|
import { getMemoryDb, getMemoryLookupLimits, storeMemoryImageAsset, storeMemoryImageFromDataUrl } from '@/lib/server/memory-db'
|
|
@@ -72,7 +72,7 @@ export async function POST(req: Request) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
const db = getMemoryDb()
|
|
75
|
-
const draftId =
|
|
75
|
+
const draftId = genId(6)
|
|
76
76
|
|
|
77
77
|
let image = body.image
|
|
78
78
|
const inputImagePath = typeof body.imagePath === 'string' ? body.imagePath.trim() : ''
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
2
3
|
import fs from 'fs'
|
|
3
4
|
import path from 'path'
|
|
4
5
|
|
|
@@ -20,7 +21,7 @@ export async function GET(_req: Request, { params }: { params: Promise<{ filenam
|
|
|
20
21
|
const filePath = path.join(IMAGES_DIR, safeName)
|
|
21
22
|
|
|
22
23
|
if (!fs.existsSync(filePath)) {
|
|
23
|
-
return
|
|
24
|
+
return notFound()
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const ext = path.extname(safeName).toLowerCase()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
export const dynamic = 'force-dynamic'
|
|
3
|
+
|
|
4
|
+
export async function GET() {
|
|
5
|
+
try {
|
|
6
|
+
const { listRunningConnectors, getRunningInstance } = await import('@/lib/server/connectors/manager')
|
|
7
|
+
const openclawConnectors = listRunningConnectors('openclaw')
|
|
8
|
+
|
|
9
|
+
if (!openclawConnectors.length) {
|
|
10
|
+
return NextResponse.json({ devices: [], note: 'No running OpenClaw connector.' })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// The directory.list RPC requires gateway support — degrade gracefully
|
|
14
|
+
return NextResponse.json({
|
|
15
|
+
devices: [],
|
|
16
|
+
connectors: openclawConnectors.map((c) => ({
|
|
17
|
+
id: c.id,
|
|
18
|
+
name: c.name,
|
|
19
|
+
platform: c.platform,
|
|
20
|
+
})),
|
|
21
|
+
note: 'Directory listing requires OpenClaw gateway directory.list RPC support.',
|
|
22
|
+
})
|
|
23
|
+
} catch (err: any) {
|
|
24
|
+
return NextResponse.json({ error: err.message || 'Directory listing failed' }, { status: 500 })
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import { probeOpenClawHealth } from '@/lib/server/openclaw-health'
|
|
4
|
+
export const dynamic = 'force-dynamic'
|
|
5
|
+
|
|
6
|
+
const DEFAULT_PORTS = [18789, 18790]
|
|
7
|
+
const PROBE_TIMEOUT_MS = 4000
|
|
8
|
+
|
|
9
|
+
function getLanIps(): string[] {
|
|
10
|
+
const interfaces = os.networkInterfaces()
|
|
11
|
+
const ips: string[] = []
|
|
12
|
+
for (const iface of Object.values(interfaces)) {
|
|
13
|
+
if (!iface) continue
|
|
14
|
+
for (const info of iface) {
|
|
15
|
+
if (info.family === 'IPv4' && !info.internal) {
|
|
16
|
+
ips.push(info.address)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return ips
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function GET() {
|
|
24
|
+
try {
|
|
25
|
+
const hosts = ['127.0.0.1', ...getLanIps()]
|
|
26
|
+
const probes: Array<Promise<{
|
|
27
|
+
host: string
|
|
28
|
+
port: number
|
|
29
|
+
healthy: boolean
|
|
30
|
+
models?: string[]
|
|
31
|
+
error?: string
|
|
32
|
+
}>> = []
|
|
33
|
+
|
|
34
|
+
for (const host of hosts) {
|
|
35
|
+
for (const port of DEFAULT_PORTS) {
|
|
36
|
+
probes.push(
|
|
37
|
+
probeOpenClawHealth({
|
|
38
|
+
endpoint: `http://${host}:${port}`,
|
|
39
|
+
timeoutMs: PROBE_TIMEOUT_MS,
|
|
40
|
+
}).then((result) => ({
|
|
41
|
+
host,
|
|
42
|
+
port,
|
|
43
|
+
healthy: result.ok,
|
|
44
|
+
models: result.models.length > 0 ? result.models : undefined,
|
|
45
|
+
error: result.error || undefined,
|
|
46
|
+
})).catch(() => ({
|
|
47
|
+
host,
|
|
48
|
+
port,
|
|
49
|
+
healthy: false,
|
|
50
|
+
error: 'unreachable',
|
|
51
|
+
})),
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const results = await Promise.all(probes)
|
|
57
|
+
return NextResponse.json({ gateways: results })
|
|
58
|
+
} catch (err: any) {
|
|
59
|
+
return NextResponse.json({ error: err.message || 'Discovery failed' }, { status: 500 })
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { runSync, type SyncType } from '@/lib/server/openclaw-sync'
|
|
3
|
+
export const dynamic = 'force-dynamic'
|
|
4
|
+
|
|
5
|
+
const VALID_ACTIONS = new Set(['push', 'pull', 'both'])
|
|
6
|
+
const VALID_TYPES: SyncType[] = ['memory', 'workspace', 'schedules', 'credentials', 'plugins']
|
|
7
|
+
|
|
8
|
+
export async function POST(req: Request) {
|
|
9
|
+
try {
|
|
10
|
+
const body = await req.json()
|
|
11
|
+
const action = body.action
|
|
12
|
+
const types = body.types
|
|
13
|
+
|
|
14
|
+
if (!action || !VALID_ACTIONS.has(action)) {
|
|
15
|
+
return NextResponse.json({ error: 'Invalid action. Use push, pull, or both.' }, { status: 400 })
|
|
16
|
+
}
|
|
17
|
+
if (!Array.isArray(types) || types.length === 0) {
|
|
18
|
+
return NextResponse.json({ error: 'types must be a non-empty array.' }, { status: 400 })
|
|
19
|
+
}
|
|
20
|
+
const validTypes = types.filter((t: string) => VALID_TYPES.includes(t as SyncType)) as SyncType[]
|
|
21
|
+
if (validTypes.length === 0) {
|
|
22
|
+
return NextResponse.json({ error: `No valid types. Use: ${VALID_TYPES.join(', ')}` }, { status: 400 })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const results = await runSync({ action, types: validTypes })
|
|
26
|
+
return NextResponse.json({ ok: true, results })
|
|
27
|
+
} catch (err: any) {
|
|
28
|
+
return NextResponse.json({ error: err.message || 'Sync failed' }, { status: 500 })
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
3
|
import { loadAgents, loadTasks, saveTasks } from '@/lib/server/storage'
|
|
4
4
|
import { enqueueTask } from '@/lib/server/queue'
|
|
5
5
|
|
|
@@ -16,7 +16,7 @@ export async function POST(req: Request) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// Create a board task and enqueue it
|
|
19
|
-
const taskId =
|
|
19
|
+
const taskId = genId()
|
|
20
20
|
const now = Date.now()
|
|
21
21
|
const tasks = loadTasks()
|
|
22
22
|
tasks[taskId] = {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { loadProjects, saveProjects, deleteProject, loadAgents, saveAgents, loadTasks, saveTasks, loadSchedules, saveSchedules, loadSkills, saveSkills } from '@/lib/server/storage'
|
|
3
|
+
import { mutateItem, deleteItem, notFound, type CollectionOps } from '@/lib/server/collection-helpers'
|
|
4
|
+
import { notify } from '@/lib/server/ws-hub'
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
const ops: CollectionOps<any> = { load: loadProjects, save: saveProjects, deleteFn: deleteProject, topic: 'projects' }
|
|
8
|
+
|
|
9
|
+
export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
10
|
+
const { id } = await params
|
|
11
|
+
const projects = loadProjects()
|
|
12
|
+
if (!projects[id]) return notFound()
|
|
13
|
+
return NextResponse.json(projects[id])
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
17
|
+
const { id } = await params
|
|
18
|
+
const body = await req.json()
|
|
19
|
+
const result = mutateItem(ops, id, (project) => {
|
|
20
|
+
Object.assign(project, body, { updatedAt: Date.now() })
|
|
21
|
+
delete (project as Record<string, unknown>).id
|
|
22
|
+
project.id = id
|
|
23
|
+
return project
|
|
24
|
+
})
|
|
25
|
+
if (!result) return notFound()
|
|
26
|
+
return NextResponse.json(result)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
30
|
+
const { id } = await params
|
|
31
|
+
if (!deleteItem(ops, id)) return notFound()
|
|
32
|
+
|
|
33
|
+
// Clear projectId from referencing entities
|
|
34
|
+
const clearProjectId = (load: () => Record<string, any>, save: (d: Record<string, any>) => void, topic: string) => {
|
|
35
|
+
const items = load()
|
|
36
|
+
let changed = false
|
|
37
|
+
for (const item of Object.values(items)) {
|
|
38
|
+
if (item.projectId === id) {
|
|
39
|
+
item.projectId = undefined
|
|
40
|
+
changed = true
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (changed) {
|
|
44
|
+
save(items)
|
|
45
|
+
notify(topic)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
clearProjectId(loadAgents, saveAgents, 'agents')
|
|
50
|
+
clearProjectId(loadTasks, saveTasks, 'tasks')
|
|
51
|
+
clearProjectId(loadSchedules, saveSchedules, 'schedules')
|
|
52
|
+
clearProjectId(loadSkills, saveSkills, 'skills')
|
|
53
|
+
|
|
54
|
+
return NextResponse.json({ ok: true })
|
|
55
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
|
+
import { loadProjects, saveProjects } from '@/lib/server/storage'
|
|
4
|
+
import { notify } from '@/lib/server/ws-hub'
|
|
5
|
+
export const dynamic = 'force-dynamic'
|
|
6
|
+
|
|
7
|
+
export async function GET(_req: Request) {
|
|
8
|
+
return NextResponse.json(loadProjects())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function POST(req: Request) {
|
|
12
|
+
const body = await req.json()
|
|
13
|
+
const id = genId()
|
|
14
|
+
const now = Date.now()
|
|
15
|
+
const projects = loadProjects()
|
|
16
|
+
projects[id] = {
|
|
17
|
+
id,
|
|
18
|
+
name: body.name || 'Unnamed Project',
|
|
19
|
+
description: body.description || '',
|
|
20
|
+
color: body.color || undefined,
|
|
21
|
+
createdAt: now,
|
|
22
|
+
updatedAt: now,
|
|
23
|
+
}
|
|
24
|
+
saveProjects(projects)
|
|
25
|
+
notify('projects')
|
|
26
|
+
return NextResponse.json(projects[id])
|
|
27
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadModelOverrides, saveModelOverrides } from '@/lib/server/storage'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
import { getProviderList } from '@/lib/providers'
|
|
4
5
|
|
|
5
6
|
export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
@@ -7,7 +8,7 @@ export async function GET(_req: Request, { params }: { params: Promise<{ id: str
|
|
|
7
8
|
const overrides = loadModelOverrides()
|
|
8
9
|
const providers = getProviderList()
|
|
9
10
|
const provider = providers.find((p) => p.id === id)
|
|
10
|
-
if (!provider) return
|
|
11
|
+
if (!provider) return notFound()
|
|
11
12
|
return NextResponse.json({ models: provider.models, hasOverride: !!overrides[id] })
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -1,37 +1,35 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadProviderConfigs, saveProviderConfigs } from '@/lib/server/storage'
|
|
3
|
-
import {
|
|
3
|
+
import { mutateItem, deleteItem, notFound, badRequest, type CollectionOps } from '@/lib/server/collection-helpers'
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
const ops: CollectionOps<any> = { load: loadProviderConfigs, save: saveProviderConfigs, topic: 'providers' }
|
|
4
7
|
|
|
5
8
|
export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
6
9
|
const { id } = await params
|
|
7
10
|
const configs = loadProviderConfigs()
|
|
8
11
|
const config = configs[id]
|
|
9
|
-
if (!config) return
|
|
12
|
+
if (!config) return notFound()
|
|
10
13
|
return NextResponse.json(config)
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
14
17
|
const { id } = await params
|
|
15
18
|
const body = await req.json()
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
notify('providers')
|
|
22
|
-
return NextResponse.json(configs[id])
|
|
19
|
+
const result = mutateItem(ops, id, (existing) => ({
|
|
20
|
+
...existing, ...body, id, updatedAt: Date.now(),
|
|
21
|
+
}))
|
|
22
|
+
if (!result) return notFound()
|
|
23
|
+
return NextResponse.json(result)
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
26
27
|
const { id } = await params
|
|
27
28
|
const configs = loadProviderConfigs()
|
|
28
|
-
if (!configs[id]) return
|
|
29
|
-
// Only allow deleting custom providers
|
|
29
|
+
if (!configs[id]) return notFound()
|
|
30
30
|
if (configs[id].type === 'builtin') {
|
|
31
|
-
return
|
|
31
|
+
return badRequest('Cannot delete built-in providers')
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
saveProviderConfigs(configs)
|
|
35
|
-
notify('providers')
|
|
33
|
+
if (!deleteItem(ops, id)) return notFound()
|
|
36
34
|
return NextResponse.json({ ok: true })
|
|
37
35
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
3
|
import { getProviderList } from '@/lib/providers'
|
|
4
4
|
import { loadProviderConfigs, saveProviderConfigs } from '@/lib/server/storage'
|
|
5
5
|
import { notify } from '@/lib/server/ws-hub'
|
|
@@ -13,7 +13,7 @@ export async function GET(_req: Request) {
|
|
|
13
13
|
export async function POST(req: Request) {
|
|
14
14
|
const body = await req.json()
|
|
15
15
|
const configs = loadProviderConfigs()
|
|
16
|
-
const id = body.id || `custom-${
|
|
16
|
+
const id = body.id || `custom-${genId()}`
|
|
17
17
|
configs[id] = {
|
|
18
18
|
id,
|
|
19
19
|
name: body.name || 'Custom Provider',
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSchedules, saveSchedules, deleteSchedule } from '@/lib/server/storage'
|
|
3
3
|
import { resolveScheduleName } from '@/lib/schedule-name'
|
|
4
|
-
import {
|
|
4
|
+
import { mutateItem, deleteItem, notFound, type CollectionOps } from '@/lib/server/collection-helpers'
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
const ops: CollectionOps<any> = { load: loadSchedules, save: saveSchedules, deleteFn: deleteSchedule, topic: 'schedules' }
|
|
5
8
|
|
|
6
9
|
export async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
7
10
|
const { id } = await params
|
|
8
11
|
const body = await req.json()
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
taskPrompt: schedules[id].taskPrompt,
|
|
12
|
+
const result = mutateItem(ops, id, (schedule) => {
|
|
13
|
+
Object.assign(schedule, body)
|
|
14
|
+
schedule.id = id
|
|
15
|
+
schedule.name = resolveScheduleName({
|
|
16
|
+
name: schedule.name,
|
|
17
|
+
taskPrompt: schedule.taskPrompt,
|
|
18
|
+
})
|
|
19
|
+
return schedule
|
|
18
20
|
})
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return NextResponse.json(schedules[id])
|
|
21
|
+
if (!result) return notFound()
|
|
22
|
+
return NextResponse.json(result)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
25
26
|
const { id } = await params
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
deleteSchedule(id)
|
|
29
|
-
notify('schedules')
|
|
30
|
-
return NextResponse.json('ok')
|
|
27
|
+
if (!deleteItem(ops, id)) return notFound()
|
|
28
|
+
return NextResponse.json({ ok: true })
|
|
31
29
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
import { loadSchedules, saveSchedules, loadAgents, loadTasks, saveTasks } from '@/lib/server/storage'
|
|
4
5
|
import { enqueueTask } from '@/lib/server/queue'
|
|
5
6
|
import { pushMainLoopEventToMainSessions } from '@/lib/server/main-agent-loop'
|
|
@@ -14,7 +15,7 @@ export async function POST(_req: Request, { params }: { params: Promise<{ id: st
|
|
|
14
15
|
const { id } = await params
|
|
15
16
|
const schedules = loadSchedules()
|
|
16
17
|
const schedule = schedules[id]
|
|
17
|
-
if (!schedule) return
|
|
18
|
+
if (!schedule) return notFound()
|
|
18
19
|
|
|
19
20
|
const agents = loadAgents()
|
|
20
21
|
const agent = agents[schedule.agentId]
|
|
@@ -64,7 +65,7 @@ export async function POST(_req: Request, { params }: { params: Promise<{ id: st
|
|
|
64
65
|
existingTask.validation = null
|
|
65
66
|
prev.runNumber = schedule.runNumber
|
|
66
67
|
} else {
|
|
67
|
-
taskId =
|
|
68
|
+
taskId = genId()
|
|
68
69
|
tasks[taskId] = {
|
|
69
70
|
id: taskId,
|
|
70
71
|
title: `[Sched] ${schedule.name} (run #${schedule.runNumber})`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
3
|
import { loadSchedules, saveSchedules } from '@/lib/server/storage'
|
|
4
4
|
import { resolveScheduleName } from '@/lib/schedule-name'
|
|
5
5
|
import { findDuplicateSchedule } from '@/lib/schedule-dedupe'
|
|
@@ -51,7 +51,7 @@ export async function POST(req: Request) {
|
|
|
51
51
|
return NextResponse.json(duplicate)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const id =
|
|
54
|
+
const id = genId()
|
|
55
55
|
|
|
56
56
|
let nextRunAt: number | undefined
|
|
57
57
|
if (scheduleType === 'once' && body.runAt) {
|
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSecrets, saveSecrets } from '@/lib/server/storage'
|
|
3
|
+
import { mutateItem, deleteItem, notFound, type CollectionOps } from '@/lib/server/collection-helpers'
|
|
4
|
+
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
const ops: CollectionOps<any> = { load: loadSecrets, save: saveSecrets }
|
|
3
7
|
|
|
4
8
|
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
5
9
|
const { id } = await params
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
delete secrets[id]
|
|
9
|
-
saveSecrets(secrets)
|
|
10
|
-
return NextResponse.json('ok')
|
|
10
|
+
if (!deleteItem(ops, id)) return notFound()
|
|
11
|
+
return NextResponse.json({ ok: true })
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export async function PUT(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
14
15
|
const { id } = await params
|
|
15
16
|
const body = await req.json()
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const { encryptedValue, ...safe } = secrets[id]
|
|
17
|
+
const result = mutateItem(ops, id, (secret) => {
|
|
18
|
+
if (body.name !== undefined) secret.name = body.name
|
|
19
|
+
if (body.service !== undefined) secret.service = body.service
|
|
20
|
+
if (body.scope !== undefined) secret.scope = body.scope
|
|
21
|
+
if (body.agentIds !== undefined) secret.agentIds = body.agentIds
|
|
22
|
+
secret.updatedAt = Date.now()
|
|
23
|
+
return secret
|
|
24
|
+
})
|
|
25
|
+
if (!result) return notFound()
|
|
26
|
+
const { encryptedValue, ...safe } = result as Record<string, any>
|
|
28
27
|
return NextResponse.json(safe)
|
|
29
28
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
3
|
import { loadSecrets, saveSecrets, encryptKey } from '@/lib/server/storage'
|
|
4
4
|
export const dynamic = 'force-dynamic'
|
|
5
5
|
|
|
@@ -18,7 +18,7 @@ export async function GET(_req: Request) {
|
|
|
18
18
|
|
|
19
19
|
export async function POST(req: Request) {
|
|
20
20
|
const body = await req.json()
|
|
21
|
-
const id =
|
|
21
|
+
const id = genId()
|
|
22
22
|
const now = Date.now()
|
|
23
23
|
const secrets = loadSecrets()
|
|
24
24
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSessions, saveSessions } from '@/lib/server/storage'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
|
|
4
5
|
export async function POST(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
5
6
|
const { id } = await params
|
|
6
7
|
const sessions = loadSessions()
|
|
7
|
-
if (!sessions[id]) return
|
|
8
|
+
if (!sessions[id]) return notFound()
|
|
8
9
|
sessions[id].messages = []
|
|
9
10
|
sessions[id].claudeSessionId = null
|
|
10
11
|
sessions[id].codexThreadId = null
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { execSync } from 'child_process'
|
|
3
3
|
import { loadSessions } from '@/lib/server/storage'
|
|
4
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
4
5
|
|
|
5
6
|
export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
6
7
|
const { id } = await params
|
|
7
8
|
const sessions = loadSessions()
|
|
8
9
|
const session = sessions[id]
|
|
9
|
-
if (!session) return
|
|
10
|
+
if (!session) return notFound()
|
|
10
11
|
|
|
11
12
|
const body = await req.json()
|
|
12
13
|
const msg = body.message || 'Deploy from SwarmClaw'
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { spawn } from 'child_process'
|
|
3
3
|
import { loadSessions, devServers, localIP } from '@/lib/server/storage'
|
|
4
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
4
5
|
|
|
5
6
|
export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
6
7
|
const { id } = await params
|
|
7
8
|
const sessions = loadSessions()
|
|
8
9
|
const session = sessions[id]
|
|
9
|
-
if (!session) return
|
|
10
|
+
if (!session) return notFound()
|
|
10
11
|
|
|
11
12
|
const { action } = await req.json()
|
|
12
13
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSessions } from '@/lib/server/storage'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
|
|
4
5
|
export async function GET(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
5
6
|
const { id } = await params
|
|
6
7
|
const sessions = loadSessions()
|
|
7
|
-
if (!sessions[id]) return
|
|
8
|
+
if (!sessions[id]) return notFound()
|
|
8
9
|
return NextResponse.json(sessions[id].messages)
|
|
9
10
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSessions, saveSessions } from '@/lib/server/storage'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
|
|
4
5
|
export async function POST(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
5
6
|
const { id } = await params
|
|
6
7
|
const sessions = loadSessions()
|
|
7
8
|
const session = sessions[id]
|
|
8
|
-
if (!session) return
|
|
9
|
+
if (!session) return notFound()
|
|
9
10
|
|
|
10
11
|
const msgs = session.messages
|
|
11
12
|
// Pop trailing assistant messages to find the last user message
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { loadSessions, saveSessions, deleteSession, active, loadAgents } from '@/lib/server/storage'
|
|
3
|
+
import { notFound } from '@/lib/server/collection-helpers'
|
|
3
4
|
import { enqueueSessionRun } from '@/lib/server/session-run-manager'
|
|
4
5
|
import { normalizeProviderEndpoint } from '@/lib/openclaw-endpoint'
|
|
5
6
|
|
|
@@ -20,7 +21,7 @@ export async function PUT(req: Request, { params }: { params: Promise<{ id: stri
|
|
|
20
21
|
const { id } = await params
|
|
21
22
|
const updates = await req.json()
|
|
22
23
|
const sessions = loadSessions()
|
|
23
|
-
if (!sessions[id]) return
|
|
24
|
+
if (!sessions[id]) return notFound()
|
|
24
25
|
const hadMessagesBefore = Array.isArray(sessions[id].messages) && sessions[id].messages.length > 0
|
|
25
26
|
|
|
26
27
|
const agentIdUpdateProvided = updates.agentId !== undefined
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
|
-
import
|
|
2
|
+
import { genId } from '@/lib/id'
|
|
3
3
|
import os from 'os'
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import { loadSessions, saveSessions, deleteSession, active, loadAgents } from '@/lib/server/storage'
|
|
@@ -46,7 +46,7 @@ export async function POST(req: Request) {
|
|
|
46
46
|
else if (cwd === '~') cwd = os.homedir()
|
|
47
47
|
else if (!cwd) cwd = WORKSPACE_DIR
|
|
48
48
|
|
|
49
|
-
const id = body.id ||
|
|
49
|
+
const id = body.id || genId()
|
|
50
50
|
const sessions = loadSessions()
|
|
51
51
|
const agent = body.agentId ? loadAgents()[body.agentId] : null
|
|
52
52
|
const requestedTools = Array.isArray(body.tools) ? body.tools : null
|