@swarmclawai/swarmclaw 0.7.0 → 0.7.2
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 +85 -139
- package/package.json +1 -1
- package/src/app/api/agents/[id]/thread/route.ts +1 -2
- package/src/app/api/agents/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/main-loop/route.ts +2 -2
- package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/route.ts +4 -52
- package/src/app/api/{sessions → chats}/route.ts +5 -7
- package/src/app/api/plugins/route.ts +3 -0
- package/src/app/api/plugins/settings/route.ts +35 -0
- package/src/app/api/usage/route.ts +30 -0
- package/src/cli/index.js +35 -33
- package/src/cli/index.ts +40 -39
- package/src/cli/spec.js +29 -27
- package/src/components/agents/agent-card.tsx +1 -1
- package/src/components/agents/agent-chat-list.tsx +3 -3
- package/src/components/agents/agent-list.tsx +8 -13
- package/src/components/agents/agent-sheet.tsx +2 -2
- package/src/components/agents/cron-job-form.tsx +3 -3
- package/src/components/agents/inspector-panel.tsx +2 -2
- package/src/components/auth/setup-wizard.tsx +5 -38
- package/src/components/chat/chat-area.tsx +10 -14
- package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +3 -3
- package/src/components/chat/chat-header.tsx +156 -73
- package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +4 -5
- package/src/components/chat/chat-tool-toggles.tsx +26 -17
- package/src/components/chat/checkpoint-timeline.tsx +4 -4
- package/src/components/chat/message-bubble.tsx +4 -1
- package/src/components/chat/message-list.tsx +2 -2
- package/src/components/{sessions/new-session-sheet.tsx → chat/new-chat-sheet.tsx} +6 -6
- package/src/components/chat/session-debug-panel.tsx +1 -1
- package/src/components/chat/tool-request-banner.tsx +3 -3
- package/src/components/chatrooms/agent-hover-card.tsx +3 -3
- package/src/components/chatrooms/chatroom-tool-request-banner.tsx +2 -2
- package/src/components/connectors/connector-sheet.tsx +1 -1
- package/src/components/home/home-view.tsx +1 -1
- package/src/components/layout/app-layout.tsx +23 -2
- package/src/components/plugins/plugin-list.tsx +475 -254
- package/src/components/plugins/plugin-sheet.tsx +124 -10
- package/src/components/settings/gateway-connection-panel.tsx +1 -1
- package/src/components/shared/command-palette.tsx +0 -1
- package/src/components/shared/settings/section-heartbeat.tsx +1 -1
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/settings-page.tsx +1 -12
- package/src/components/usage/metrics-dashboard.tsx +73 -0
- package/src/components/webhooks/webhook-sheet.tsx +1 -1
- package/src/lib/chat.ts +1 -1
- package/src/lib/{sessions.ts → chats.ts} +28 -18
- package/src/lib/providers/claude-cli.ts +1 -1
- package/src/lib/server/approvals.ts +4 -4
- package/src/lib/server/capability-router.ts +10 -8
- package/src/lib/server/chat-execution.ts +36 -105
- package/src/lib/server/chatroom-helpers.ts +3 -3
- package/src/lib/server/connectors/manager.ts +4 -4
- package/src/lib/server/cost.ts +34 -1
- package/src/lib/server/daemon-state.ts +2 -2
- package/src/lib/server/heartbeat-service.ts +1 -1
- package/src/lib/server/main-agent-loop.ts +25 -160
- package/src/lib/server/main-session.ts +6 -13
- package/src/lib/server/orchestrator-lg.ts +3 -3
- package/src/lib/server/orchestrator.ts +5 -5
- package/src/lib/server/plugins.ts +112 -4
- package/src/lib/server/provider-health.ts +5 -3
- package/src/lib/server/queue.ts +12 -10
- package/src/lib/server/session-run-manager.test.ts +9 -6
- package/src/lib/server/session-run-manager.ts +1 -3
- package/src/lib/server/session-tools/calendar.ts +376 -0
- package/src/lib/server/session-tools/canvas.ts +1 -1
- package/src/lib/server/session-tools/chatroom.ts +4 -2
- package/src/lib/server/session-tools/connector.ts +5 -2
- package/src/lib/server/session-tools/context.ts +7 -3
- package/src/lib/server/session-tools/crud.ts +14 -6
- package/src/lib/server/session-tools/delegate.ts +95 -8
- package/src/lib/server/session-tools/discovery.ts +2 -2
- package/src/lib/server/session-tools/edit_file.ts +4 -2
- package/src/lib/server/session-tools/email.ts +322 -0
- package/src/lib/server/session-tools/file.ts +5 -2
- package/src/lib/server/session-tools/git.ts +1 -1
- package/src/lib/server/session-tools/http.ts +1 -1
- package/src/lib/server/session-tools/image-gen.ts +382 -0
- package/src/lib/server/session-tools/index.ts +74 -49
- package/src/lib/server/session-tools/memory.ts +139 -2
- package/src/lib/server/session-tools/monitor.ts +1 -1
- package/src/lib/server/session-tools/openclaw-nodes.ts +1 -1
- package/src/lib/server/session-tools/openclaw-workspace.ts +1 -1
- package/src/lib/server/session-tools/platform.ts +6 -3
- package/src/lib/server/session-tools/plugin-creator.ts +3 -3
- package/src/lib/server/session-tools/replicate.ts +303 -0
- package/src/lib/server/session-tools/sample-ui.ts +1 -1
- package/src/lib/server/session-tools/sandbox.ts +4 -2
- package/src/lib/server/session-tools/schedule.ts +4 -2
- package/src/lib/server/session-tools/session-info.ts +7 -4
- package/src/lib/server/session-tools/shell.ts +5 -2
- package/src/lib/server/session-tools/subagent.ts +2 -2
- package/src/lib/server/session-tools/wallet.ts +29 -2
- package/src/lib/server/session-tools/web.ts +51 -6
- package/src/lib/server/storage.ts +29 -9
- package/src/lib/server/stream-agent-chat.ts +72 -249
- package/src/lib/server/tool-aliases.ts +26 -15
- package/src/lib/server/tool-capability-policy.test.ts +9 -9
- package/src/lib/server/tool-capability-policy.ts +32 -27
- package/src/lib/tool-definitions.ts +4 -0
- package/src/lib/validation/schemas.ts +3 -1
- package/src/stores/use-app-store.ts +5 -5
- package/src/stores/use-chat-store.ts +7 -7
- package/src/types/index.ts +65 -3
- /package/src/app/api/{sessions → chats}/[id]/browser/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/chat/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/clear/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/deploy/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/devserver/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/edit-resend/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/fork/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/mailbox/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/messages/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/retry/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/[id]/stop/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { getPluginManager } from '@/lib/server/plugins'
|
|
3
|
+
import { notify } from '@/lib/server/ws-hub'
|
|
3
4
|
|
|
4
5
|
// Ensure all builtin plugins are registered by importing their modules
|
|
5
6
|
import '@/lib/server/session-tools/shell'
|
|
@@ -44,6 +45,7 @@ export async function POST(req: Request) {
|
|
|
44
45
|
|
|
45
46
|
const manager = getPluginManager()
|
|
46
47
|
manager.setEnabled(filename, enabled)
|
|
48
|
+
notify('plugins')
|
|
47
49
|
|
|
48
50
|
return NextResponse.json({ ok: true })
|
|
49
51
|
}
|
|
@@ -59,6 +61,7 @@ export async function DELETE(req: Request) {
|
|
|
59
61
|
if (!deleted) {
|
|
60
62
|
return NextResponse.json({ error: 'Cannot delete built-in or non-existent plugin' }, { status: 400 })
|
|
61
63
|
}
|
|
64
|
+
notify('plugins')
|
|
62
65
|
return NextResponse.json({ ok: true })
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { loadSettings, saveSettings } from '@/lib/server/storage'
|
|
3
|
+
|
|
4
|
+
export const dynamic = 'force-dynamic'
|
|
5
|
+
|
|
6
|
+
/** GET /api/plugins/settings?pluginId=X — read per-plugin settings */
|
|
7
|
+
export async function GET(req: Request) {
|
|
8
|
+
const { searchParams } = new URL(req.url)
|
|
9
|
+
const pluginId = searchParams.get('pluginId')
|
|
10
|
+
if (!pluginId) {
|
|
11
|
+
return NextResponse.json({ error: 'pluginId required' }, { status: 400 })
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const settings = loadSettings()
|
|
15
|
+
const pluginSettings = (settings.pluginSettings as Record<string, Record<string, unknown>> | undefined) ?? {}
|
|
16
|
+
return NextResponse.json(pluginSettings[pluginId] ?? {})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** PUT /api/plugins/settings?pluginId=X — write per-plugin settings */
|
|
20
|
+
export async function PUT(req: Request) {
|
|
21
|
+
const { searchParams } = new URL(req.url)
|
|
22
|
+
const pluginId = searchParams.get('pluginId')
|
|
23
|
+
if (!pluginId) {
|
|
24
|
+
return NextResponse.json({ error: 'pluginId required' }, { status: 400 })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const body = await req.json() as Record<string, unknown>
|
|
28
|
+
const settings = loadSettings()
|
|
29
|
+
const pluginSettings = (settings.pluginSettings as Record<string, Record<string, unknown>> | undefined) ?? {}
|
|
30
|
+
pluginSettings[pluginId] = body
|
|
31
|
+
settings.pluginSettings = pluginSettings
|
|
32
|
+
saveSettings(settings)
|
|
33
|
+
|
|
34
|
+
return NextResponse.json({ ok: true })
|
|
35
|
+
}
|
|
@@ -50,6 +50,7 @@ export async function GET(req: Request) {
|
|
|
50
50
|
let totalCost = 0
|
|
51
51
|
const byAgent: Record<string, { name: string; cost: number; tokens: number; count: number }> = {}
|
|
52
52
|
const byProvider: Record<string, { tokens: number; cost: number }> = {}
|
|
53
|
+
const byPlugin: Record<string, { definitionTokens: number; invocationTokens: number; invocations: number; estimatedCost: number }> = {}
|
|
53
54
|
const bucketMap: Record<string, { tokens: number; cost: number }> = {}
|
|
54
55
|
|
|
55
56
|
for (const r of records) {
|
|
@@ -75,6 +76,26 @@ export async function GET(req: Request) {
|
|
|
75
76
|
byAgent[agentId].tokens += tokens
|
|
76
77
|
byAgent[agentId].count += 1
|
|
77
78
|
|
|
79
|
+
// by plugin — definition costs (context overhead per LLM call)
|
|
80
|
+
if (Array.isArray(r.pluginDefinitionCosts)) {
|
|
81
|
+
for (const dc of r.pluginDefinitionCosts) {
|
|
82
|
+
if (!dc.pluginId) continue
|
|
83
|
+
if (!byPlugin[dc.pluginId]) byPlugin[dc.pluginId] = { definitionTokens: 0, invocationTokens: 0, invocations: 0, estimatedCost: 0 }
|
|
84
|
+
byPlugin[dc.pluginId].definitionTokens += dc.estimatedTokens || 0
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// by plugin — invocation costs (actual tool calls)
|
|
89
|
+
if (Array.isArray(r.pluginInvocations)) {
|
|
90
|
+
for (const inv of r.pluginInvocations) {
|
|
91
|
+
if (!inv.pluginId) continue
|
|
92
|
+
if (!byPlugin[inv.pluginId]) byPlugin[inv.pluginId] = { definitionTokens: 0, invocationTokens: 0, invocations: 0, estimatedCost: 0 }
|
|
93
|
+
const p = byPlugin[inv.pluginId]
|
|
94
|
+
p.invocationTokens += (inv.inputTokens || 0) + (inv.outputTokens || 0)
|
|
95
|
+
p.invocations += 1
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
78
99
|
// time series bucketing
|
|
79
100
|
const bk = bucketKey(r.timestamp || now, range)
|
|
80
101
|
if (!bucketMap[bk]) bucketMap[bk] = { tokens: 0, cost: 0 }
|
|
@@ -82,6 +103,14 @@ export async function GET(req: Request) {
|
|
|
82
103
|
bucketMap[bk].cost += cost
|
|
83
104
|
}
|
|
84
105
|
|
|
106
|
+
// Estimate per-plugin cost using the average input token rate from total usage
|
|
107
|
+
if (totalTokens > 0 && totalCost > 0) {
|
|
108
|
+
const avgCostPerToken = totalCost / totalTokens
|
|
109
|
+
for (const p of Object.values(byPlugin)) {
|
|
110
|
+
p.estimatedCost = Math.round((p.definitionTokens + p.invocationTokens) * avgCostPerToken * 10000) / 10000
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
85
114
|
// Sort time series
|
|
86
115
|
const timeSeries = Object.entries(bucketMap)
|
|
87
116
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
@@ -144,6 +173,7 @@ export async function GET(req: Request) {
|
|
|
144
173
|
totalCost: Math.round(totalCost * 10000) / 10000,
|
|
145
174
|
byAgent,
|
|
146
175
|
byProvider,
|
|
176
|
+
byPlugin,
|
|
147
177
|
timeSeries,
|
|
148
178
|
providerHealth,
|
|
149
179
|
})
|
package/src/cli/index.js
CHANGED
|
@@ -345,6 +345,8 @@ const COMMAND_GROUPS = [
|
|
|
345
345
|
cmd('update', 'PATCH', '/plugins', 'Update a plugin (use --query id=plugin.js or --query all=true)'),
|
|
346
346
|
cmd('install', 'POST', '/plugins/install', 'Install plugin from URL', { expectsJsonBody: true }),
|
|
347
347
|
cmd('marketplace', 'GET', '/plugins/marketplace', 'Get marketplace catalog'),
|
|
348
|
+
cmd('settings-get', 'GET', '/plugins/settings', 'Get plugin settings (use --query pluginId=plugin_name)'),
|
|
349
|
+
cmd('settings-set', 'PUT', '/plugins/settings', 'Set plugin settings (use --query pluginId=plugin_name and --data JSON)', { expectsJsonBody: true }),
|
|
348
350
|
cmd('ui', 'GET', '/plugins/ui', 'List plugin UI extensions (use --query type=sidebar|header|chat_actions|connectors)'),
|
|
349
351
|
],
|
|
350
352
|
},
|
|
@@ -369,7 +371,7 @@ const COMMAND_GROUPS = [
|
|
|
369
371
|
name: 'search',
|
|
370
372
|
description: 'Global search across app resources',
|
|
371
373
|
commands: [
|
|
372
|
-
cmd('query', 'GET', '/search', 'Search agents/tasks/
|
|
374
|
+
cmd('query', 'GET', '/search', 'Search agents/tasks/chats/schedules/webhooks/skills (use --query q=term)'),
|
|
373
375
|
],
|
|
374
376
|
},
|
|
375
377
|
{
|
|
@@ -404,56 +406,56 @@ const COMMAND_GROUPS = [
|
|
|
404
406
|
],
|
|
405
407
|
},
|
|
406
408
|
{
|
|
407
|
-
name: '
|
|
408
|
-
description: 'Manage
|
|
409
|
+
name: 'chats',
|
|
410
|
+
description: 'Manage agent chats and runtime controls',
|
|
409
411
|
commands: [
|
|
410
|
-
cmd('list', 'GET', '/
|
|
411
|
-
cmd('get', 'GET', '/
|
|
412
|
-
cmd('create', 'POST', '/
|
|
413
|
-
cmd('update', 'PUT', '/
|
|
414
|
-
cmd('delete', 'DELETE', '/
|
|
415
|
-
cmd('delete-many', 'DELETE', '/
|
|
416
|
-
cmd('heartbeat-disable-all', 'POST', '/
|
|
412
|
+
cmd('list', 'GET', '/chats', 'List chats'),
|
|
413
|
+
cmd('get', 'GET', '/chats/:id', 'Get chat by id', { virtual: true, clientGetRoute: '/chats' }),
|
|
414
|
+
cmd('create', 'POST', '/chats', 'Create chat', { expectsJsonBody: true }),
|
|
415
|
+
cmd('update', 'PUT', '/chats/:id', 'Update chat', { expectsJsonBody: true }),
|
|
416
|
+
cmd('delete', 'DELETE', '/chats/:id', 'Delete chat'),
|
|
417
|
+
cmd('delete-many', 'DELETE', '/chats', 'Delete multiple chats (body: {"ids":[...]})', { expectsJsonBody: true }),
|
|
418
|
+
cmd('heartbeat-disable-all', 'POST', '/chats/heartbeat', 'Disable all chat heartbeats and cancel queued heartbeat runs', {
|
|
417
419
|
expectsJsonBody: true,
|
|
418
420
|
defaultBody: { action: 'disable_all' },
|
|
419
421
|
}),
|
|
420
|
-
cmd('messages', 'GET', '/
|
|
421
|
-
cmd('messages-update', 'PUT', '/
|
|
422
|
-
cmd('messages-send', 'POST', '/
|
|
423
|
-
cmd('messages-delete', 'DELETE', '/
|
|
424
|
-
cmd('fork', 'POST', '/
|
|
425
|
-
cmd('edit-resend', 'POST', '/
|
|
426
|
-
cmd('main-loop', 'GET', '/
|
|
427
|
-
cmd('main-loop-action', 'POST', '/
|
|
422
|
+
cmd('messages', 'GET', '/chats/:id/messages', 'Get chat messages'),
|
|
423
|
+
cmd('messages-update', 'PUT', '/chats/:id/messages', 'Update chat message metadata (e.g. bookmark)', { expectsJsonBody: true }),
|
|
424
|
+
cmd('messages-send', 'POST', '/chats/:id/messages', 'Append a user/system message to a chat', { expectsJsonBody: true }),
|
|
425
|
+
cmd('messages-delete', 'DELETE', '/chats/:id/messages', 'Delete a message from a chat', { expectsJsonBody: true }),
|
|
426
|
+
cmd('fork', 'POST', '/chats/:id/fork', 'Fork chat from a specific message index', { expectsJsonBody: true }),
|
|
427
|
+
cmd('edit-resend', 'POST', '/chats/:id/edit-resend', 'Edit and resend from a specific message index', { expectsJsonBody: true }),
|
|
428
|
+
cmd('main-loop', 'GET', '/chats/:id/main-loop', 'Get main mission loop state'),
|
|
429
|
+
cmd('main-loop-action', 'POST', '/chats/:id/main-loop', 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', {
|
|
428
430
|
expectsJsonBody: true,
|
|
429
431
|
}),
|
|
430
|
-
cmd('chat', 'POST', '/
|
|
432
|
+
cmd('chat', 'POST', '/chats/:id/chat', 'Send chat message (streaming)', {
|
|
431
433
|
expectsJsonBody: true,
|
|
432
434
|
responseType: 'sse',
|
|
433
435
|
}),
|
|
434
|
-
cmd('stop', 'POST', '/
|
|
435
|
-
cmd('clear', 'POST', '/
|
|
436
|
-
cmd('browser-status', 'GET', '/
|
|
437
|
-
cmd('browser-close', 'DELETE', '/
|
|
438
|
-
cmd('mailbox', 'GET', '/
|
|
439
|
-
cmd('mailbox-action', 'POST', '/
|
|
440
|
-
cmd('retry', 'POST', '/
|
|
441
|
-
cmd('deploy', 'POST', '/
|
|
442
|
-
cmd('devserver', 'POST', '/
|
|
443
|
-
cmd('devserver-start', 'POST', '/
|
|
436
|
+
cmd('stop', 'POST', '/chats/:id/stop', 'Stop chat run(s)'),
|
|
437
|
+
cmd('clear', 'POST', '/chats/:id/clear', 'Clear chat messages'),
|
|
438
|
+
cmd('browser-status', 'GET', '/chats/:id/browser', 'Check browser status'),
|
|
439
|
+
cmd('browser-close', 'DELETE', '/chats/:id/browser', 'Close browser'),
|
|
440
|
+
cmd('mailbox', 'GET', '/chats/:id/mailbox', 'List chat mailbox envelopes'),
|
|
441
|
+
cmd('mailbox-action', 'POST', '/chats/:id/mailbox', 'Send/ack/clear mailbox envelopes', { expectsJsonBody: true }),
|
|
442
|
+
cmd('retry', 'POST', '/chats/:id/retry', 'Retry last assistant message'),
|
|
443
|
+
cmd('deploy', 'POST', '/chats/:id/deploy', 'Deploy current chat branch', { expectsJsonBody: true }),
|
|
444
|
+
cmd('devserver', 'POST', '/chats/:id/devserver', 'Dev server action via JSON body', { expectsJsonBody: true }),
|
|
445
|
+
cmd('devserver-start', 'POST', '/chats/:id/devserver', 'Start chat dev server', {
|
|
444
446
|
expectsJsonBody: true,
|
|
445
447
|
defaultBody: { action: 'start' },
|
|
446
448
|
}),
|
|
447
|
-
cmd('devserver-stop', 'POST', '/
|
|
449
|
+
cmd('devserver-stop', 'POST', '/chats/:id/devserver', 'Stop chat dev server', {
|
|
448
450
|
expectsJsonBody: true,
|
|
449
451
|
defaultBody: { action: 'stop' },
|
|
450
452
|
}),
|
|
451
|
-
cmd('devserver-status', 'POST', '/
|
|
453
|
+
cmd('devserver-status', 'POST', '/chats/:id/devserver', 'Check chat dev server status', {
|
|
452
454
|
expectsJsonBody: true,
|
|
453
455
|
defaultBody: { action: 'status' },
|
|
454
456
|
}),
|
|
455
|
-
cmd('checkpoints', 'GET', '/
|
|
456
|
-
cmd('restore', 'POST', '/
|
|
457
|
+
cmd('checkpoints', 'GET', '/chats/:id/checkpoints', 'List checkpoint history for a chat'),
|
|
458
|
+
cmd('restore', 'POST', '/chats/:id/restore', 'Restore chat to a previous checkpoint', { expectsJsonBody: true }),
|
|
457
459
|
],
|
|
458
460
|
},
|
|
459
461
|
{
|
package/src/cli/index.ts
CHANGED
|
@@ -657,27 +657,28 @@ export function buildProgram(): Command {
|
|
|
657
657
|
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/runs/${encodeURIComponent(id)}`))
|
|
658
658
|
})
|
|
659
659
|
|
|
660
|
-
const
|
|
660
|
+
const chats = program.command('chats').description('Manage chats')
|
|
661
|
+
program.command('sessions').description('Manage chats (alias)').action(() => chats.help())
|
|
661
662
|
|
|
662
|
-
|
|
663
|
+
chats
|
|
663
664
|
.command('list')
|
|
664
|
-
.description('List
|
|
665
|
+
.description('List chats')
|
|
665
666
|
.action(async function () {
|
|
666
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', '/
|
|
667
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', '/chats'))
|
|
667
668
|
})
|
|
668
669
|
|
|
669
|
-
|
|
670
|
+
chats
|
|
670
671
|
.command('get')
|
|
671
|
-
.description('Get
|
|
672
|
-
.argument('<id>', '
|
|
672
|
+
.description('Get chat by id')
|
|
673
|
+
.argument('<id>', 'Chat id')
|
|
673
674
|
.action(async function (id: string) {
|
|
674
|
-
await runWithHandler(this as Command, (ctx) => resolveByIdFromCollection(ctx, '/
|
|
675
|
+
await runWithHandler(this as Command, (ctx) => resolveByIdFromCollection(ctx, '/chats', id))
|
|
675
676
|
})
|
|
676
677
|
|
|
677
|
-
|
|
678
|
+
chats
|
|
678
679
|
.command('create')
|
|
679
|
-
.description('Create
|
|
680
|
-
.option('--name <name>', '
|
|
680
|
+
.description('Create chat')
|
|
681
|
+
.option('--name <name>', 'Chat name', 'New Chat')
|
|
681
682
|
.option('--user <user>', 'User name')
|
|
682
683
|
.option('--cwd <cwd>', 'Working directory')
|
|
683
684
|
.option('--provider <provider>', 'Provider id')
|
|
@@ -706,7 +707,7 @@ export function buildProgram(): Command {
|
|
|
706
707
|
if (opts.heartbeatIntervalSec && (!Number.isFinite(heartbeatIntervalSec) || heartbeatIntervalSec! < 0)) {
|
|
707
708
|
throw new Error(`Invalid --heartbeat-interval-sec value: ${opts.heartbeatIntervalSec}`)
|
|
708
709
|
}
|
|
709
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', '/
|
|
710
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', '/chats', compactObject({
|
|
710
711
|
name: opts.name,
|
|
711
712
|
user: opts.user,
|
|
712
713
|
cwd: opts.cwd,
|
|
@@ -720,14 +721,14 @@ export function buildProgram(): Command {
|
|
|
720
721
|
})))
|
|
721
722
|
})
|
|
722
723
|
|
|
723
|
-
|
|
724
|
+
chats
|
|
724
725
|
.command('update')
|
|
725
|
-
.description('Update
|
|
726
|
-
.argument('<id>', '
|
|
727
|
-
.option('--name <name>', '
|
|
726
|
+
.description('Update chat')
|
|
727
|
+
.argument('<id>', 'Chat id')
|
|
728
|
+
.option('--name <name>', 'Chat name')
|
|
728
729
|
.option('--cwd <cwd>', 'Working directory')
|
|
729
730
|
.option('--agent-id <agentId>', 'Agent id')
|
|
730
|
-
.option('--
|
|
731
|
+
.option('--plugins <json>', 'Plugins JSON array, e.g. ["shell","memory"]')
|
|
731
732
|
.option('--heartbeat-enabled <heartbeatEnabled>', 'Heartbeat enabled (true|false)')
|
|
732
733
|
.option('--heartbeat-interval-sec <heartbeatIntervalSec>', 'Heartbeat interval seconds')
|
|
733
734
|
.action(async function (
|
|
@@ -736,7 +737,7 @@ export function buildProgram(): Command {
|
|
|
736
737
|
name?: string
|
|
737
738
|
cwd?: string
|
|
738
739
|
agentId?: string
|
|
739
|
-
|
|
740
|
+
plugins?: string
|
|
740
741
|
heartbeatEnabled?: string
|
|
741
742
|
heartbeatIntervalSec?: string
|
|
742
743
|
},
|
|
@@ -748,40 +749,40 @@ export function buildProgram(): Command {
|
|
|
748
749
|
if (opts.heartbeatIntervalSec && (!Number.isFinite(heartbeatIntervalSec) || heartbeatIntervalSec! < 0)) {
|
|
749
750
|
throw new Error(`Invalid --heartbeat-interval-sec value: ${opts.heartbeatIntervalSec}`)
|
|
750
751
|
}
|
|
751
|
-
const
|
|
752
|
-
if (
|
|
753
|
-
throw new Error('--
|
|
752
|
+
const plugins = parseJsonValue(opts.plugins, '--plugins')
|
|
753
|
+
if (plugins !== undefined && !Array.isArray(plugins)) {
|
|
754
|
+
throw new Error('--plugins must be a JSON array')
|
|
754
755
|
}
|
|
755
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'PUT', `/
|
|
756
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'PUT', `/chats/${encodeURIComponent(id)}`, compactObject({
|
|
756
757
|
name: opts.name,
|
|
757
758
|
cwd: opts.cwd,
|
|
758
759
|
agentId: opts.agentId,
|
|
759
|
-
|
|
760
|
+
plugins,
|
|
760
761
|
heartbeatEnabled: typeof opts.heartbeatEnabled === 'string' ? heartbeatEnabled : undefined,
|
|
761
762
|
heartbeatIntervalSec,
|
|
762
763
|
})))
|
|
763
764
|
})
|
|
764
765
|
|
|
765
|
-
|
|
766
|
+
chats
|
|
766
767
|
.command('delete')
|
|
767
|
-
.description('Delete
|
|
768
|
-
.argument('<id>', '
|
|
768
|
+
.description('Delete chat')
|
|
769
|
+
.argument('<id>', 'Chat id')
|
|
769
770
|
.action(async function (id: string) {
|
|
770
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'DELETE', `/
|
|
771
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'DELETE', `/chats/${encodeURIComponent(id)}`))
|
|
771
772
|
})
|
|
772
773
|
|
|
773
|
-
|
|
774
|
+
chats
|
|
774
775
|
.command('history')
|
|
775
|
-
.description('Get
|
|
776
|
-
.argument('<id>', '
|
|
776
|
+
.description('Get chat message history')
|
|
777
|
+
.argument('<id>', 'Chat id')
|
|
777
778
|
.action(async function (id: string) {
|
|
778
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/
|
|
779
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'GET', `/chats/${encodeURIComponent(id)}/messages`))
|
|
779
780
|
})
|
|
780
781
|
|
|
781
|
-
|
|
782
|
+
chats
|
|
782
783
|
.command('mailbox')
|
|
783
|
-
.description('List
|
|
784
|
-
.argument('<id>', '
|
|
784
|
+
.description('List chat mailbox envelopes')
|
|
785
|
+
.argument('<id>', 'Chat id')
|
|
785
786
|
.option('--limit <limit>', 'Max envelopes to return (default: 50)')
|
|
786
787
|
.option('--include-acked', 'Include acknowledged envelopes')
|
|
787
788
|
.action(async function (
|
|
@@ -799,16 +800,16 @@ export function buildProgram(): Command {
|
|
|
799
800
|
const params = new URLSearchParams()
|
|
800
801
|
if (typeof limit === 'number') params.set('limit', String(limit))
|
|
801
802
|
if (opts.includeAcked) params.set('includeAcked', '1')
|
|
802
|
-
return apiRequest(ctx, 'GET', `/
|
|
803
|
+
return apiRequest(ctx, 'GET', `/chats/${encodeURIComponent(id)}/mailbox`, undefined, params)
|
|
803
804
|
})
|
|
804
805
|
})
|
|
805
806
|
|
|
806
|
-
|
|
807
|
+
chats
|
|
807
808
|
.command('stop')
|
|
808
|
-
.description('Stop running work for a
|
|
809
|
-
.argument('<id>', '
|
|
809
|
+
.description('Stop running work for a chat')
|
|
810
|
+
.argument('<id>', 'Chat id')
|
|
810
811
|
.action(async function (id: string) {
|
|
811
|
-
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', `/
|
|
812
|
+
await runWithHandler(this as Command, (ctx) => apiRequest(ctx, 'POST', `/chats/${encodeURIComponent(id)}/stop`))
|
|
812
813
|
})
|
|
813
814
|
|
|
814
815
|
const memory = program.command('memory').description('Manage memory')
|
package/src/cli/spec.js
CHANGED
|
@@ -228,6 +228,8 @@ const COMMAND_GROUPS = {
|
|
|
228
228
|
update: { description: 'Enable/disable plugin (body: {"filename":"x.js","enabled":true})', method: 'POST', path: '/plugins' },
|
|
229
229
|
marketplace: { description: 'Get plugin marketplace registry', method: 'GET', path: '/plugins/marketplace' },
|
|
230
230
|
install: { description: 'Install plugin by URL', method: 'POST', path: '/plugins/install' },
|
|
231
|
+
'settings-get': { description: 'Read plugin settings (supports --query pluginId=...)', method: 'GET', path: '/plugins/settings' },
|
|
232
|
+
'settings-set': { description: 'Write plugin settings (supports --query pluginId=... and --data JSON)', method: 'PUT', path: '/plugins/settings' },
|
|
231
233
|
},
|
|
232
234
|
},
|
|
233
235
|
providers: {
|
|
@@ -249,7 +251,7 @@ const COMMAND_GROUPS = {
|
|
|
249
251
|
search: {
|
|
250
252
|
description: 'Global search across app resources',
|
|
251
253
|
commands: {
|
|
252
|
-
query: { description: 'Search agents/tasks/
|
|
254
|
+
query: { description: 'Search agents/tasks/chats/schedules/webhooks/skills (supports --query q=term)', method: 'GET', path: '/search' },
|
|
253
255
|
},
|
|
254
256
|
},
|
|
255
257
|
schedules: {
|
|
@@ -273,33 +275,33 @@ const COMMAND_GROUPS = {
|
|
|
273
275
|
delete: { description: 'Delete secret', method: 'DELETE', path: '/secrets/:id', params: ['id'] },
|
|
274
276
|
},
|
|
275
277
|
},
|
|
276
|
-
|
|
277
|
-
description: '
|
|
278
|
+
chats: {
|
|
279
|
+
description: 'Agent chats',
|
|
278
280
|
commands: {
|
|
279
|
-
list: { description: 'List
|
|
280
|
-
create: { description: 'Create
|
|
281
|
-
get: { description: 'Get
|
|
282
|
-
update: { description: 'Update
|
|
283
|
-
delete: { description: 'Delete one
|
|
284
|
-
'delete-many': { description: 'Delete multiple
|
|
285
|
-
'heartbeat-disable-all': { description: 'Disable all
|
|
286
|
-
messages: { description: 'Get
|
|
287
|
-
'messages-update': { description: 'Update
|
|
288
|
-
'messages-send': { description: 'Append a user/system message to a
|
|
289
|
-
'messages-delete': { description: 'Delete a message from a
|
|
290
|
-
fork: { description: 'Fork
|
|
291
|
-
'edit-resend': { description: 'Edit and resend from a specific message index', method: 'POST', path: '/
|
|
292
|
-
'main-loop': { description: 'Get main mission loop state for a
|
|
293
|
-
'main-loop-action': { description: 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', method: 'POST', path: '/
|
|
294
|
-
chat: { description: 'Send chat message (SSE stream)', method: 'POST', path: '/
|
|
295
|
-
stop: { description: 'Cancel active/running
|
|
296
|
-
clear: { description: 'Clear
|
|
297
|
-
mailbox: { description: 'List mailbox envelopes for a
|
|
298
|
-
'mailbox-action': { description: 'Send/ack/clear mailbox envelopes', method: 'POST', path: '/
|
|
299
|
-
deploy: { description: 'Deploy
|
|
300
|
-
devserver: { description: 'Start/stop/status dev server (body: {"action":"start|stop|status"})', method: 'POST', path: '/
|
|
301
|
-
browser: { description: 'Check browser runtime for
|
|
302
|
-
'browser-clear': { description: 'Close browser runtime for
|
|
281
|
+
list: { description: 'List chats', method: 'GET', path: '/chats' },
|
|
282
|
+
create: { description: 'Create chat', method: 'POST', path: '/chats' },
|
|
283
|
+
get: { description: 'Get chat by id (from list)', virtualGet: true, collectionPath: '/chats', params: ['id'] },
|
|
284
|
+
update: { description: 'Update chat fields', method: 'PUT', path: '/chats/:id', params: ['id'] },
|
|
285
|
+
delete: { description: 'Delete one chat', method: 'DELETE', path: '/chats/:id', params: ['id'] },
|
|
286
|
+
'delete-many': { description: 'Delete multiple chats (body: {"ids":[...]})', method: 'DELETE', path: '/chats' },
|
|
287
|
+
'heartbeat-disable-all': { description: 'Disable all chat heartbeats and cancel queued heartbeat runs', method: 'POST', path: '/chats/heartbeat' },
|
|
288
|
+
messages: { description: 'Get chat message history', method: 'GET', path: '/chats/:id/messages', params: ['id'] },
|
|
289
|
+
'messages-update': { description: 'Update chat message metadata (e.g. bookmark)', method: 'PUT', path: '/chats/:id/messages', params: ['id'] },
|
|
290
|
+
'messages-send': { description: 'Append a user/system message to a chat', method: 'POST', path: '/chats/:id/messages', params: ['id'] },
|
|
291
|
+
'messages-delete': { description: 'Delete a message from a chat', method: 'DELETE', path: '/chats/:id/messages', params: ['id'] },
|
|
292
|
+
fork: { description: 'Fork chat from a specific message index', method: 'POST', path: '/chats/:id/fork', params: ['id'] },
|
|
293
|
+
'edit-resend': { description: 'Edit and resend from a specific message index', method: 'POST', path: '/chats/:id/edit-resend', params: ['id'] },
|
|
294
|
+
'main-loop': { description: 'Get main mission loop state for a chat', method: 'GET', path: '/chats/:id/main-loop', params: ['id'] },
|
|
295
|
+
'main-loop-action': { description: 'Control main mission loop (pause/resume/set_goal/set_mode/clear_events/nudge)', method: 'POST', path: '/chats/:id/main-loop', params: ['id'] },
|
|
296
|
+
chat: { description: 'Send chat message (SSE stream)', method: 'POST', path: '/chats/:id/chat', params: ['id'], stream: true, waitable: true },
|
|
297
|
+
stop: { description: 'Cancel active/running chat work', method: 'POST', path: '/chats/:id/stop', params: ['id'] },
|
|
298
|
+
clear: { description: 'Clear chat history', method: 'POST', path: '/chats/:id/clear', params: ['id'] },
|
|
299
|
+
mailbox: { description: 'List mailbox envelopes for a chat', method: 'GET', path: '/chats/:id/mailbox', params: ['id'] },
|
|
300
|
+
'mailbox-action': { description: 'Send/ack/clear mailbox envelopes', method: 'POST', path: '/chats/:id/mailbox', params: ['id'] },
|
|
301
|
+
deploy: { description: 'Deploy chat workspace git changes', method: 'POST', path: '/chats/:id/deploy', params: ['id'] },
|
|
302
|
+
devserver: { description: 'Start/stop/status dev server (body: {"action":"start|stop|status"})', method: 'POST', path: '/chats/:id/devserver', params: ['id'] },
|
|
303
|
+
browser: { description: 'Check browser runtime for chat', method: 'GET', path: '/chats/:id/browser', params: ['id'] },
|
|
304
|
+
'browser-clear': { description: 'Close browser runtime for chat', method: 'DELETE', path: '/chats/:id/browser', params: ['id'] },
|
|
303
305
|
},
|
|
304
306
|
},
|
|
305
307
|
settings: {
|
|
@@ -220,7 +220,7 @@ export function AgentCard({ agent, isDefault, isRunning, isOnline, isSelected, o
|
|
|
220
220
|
<div className="text-[12px] text-text-3/70 mt-1.5 truncate">{agent.description}</div>
|
|
221
221
|
<div className="flex items-center gap-2 mt-1.5">
|
|
222
222
|
<span className="text-[11px] text-text-3/60 font-mono">{agent.model || agent.provider}</span>
|
|
223
|
-
{agent.
|
|
223
|
+
{agent.plugins?.includes('browser') && (
|
|
224
224
|
<span className="text-[10px] font-600 uppercase tracking-wider text-sky-400/70 bg-sky-400/[0.08] px-1.5 py-0.5 rounded-[5px]">
|
|
225
225
|
browser
|
|
226
226
|
</span>
|
|
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } fr
|
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { useChatStore } from '@/stores/use-chat-store'
|
|
6
6
|
import { useChatroomStore } from '@/stores/use-chatroom-store'
|
|
7
|
-
import { fetchMessages } from '@/lib/
|
|
7
|
+
import { fetchMessages } from '@/lib/chats'
|
|
8
8
|
import { api } from '@/lib/api-client'
|
|
9
9
|
import { ConfirmDialog } from '@/components/shared/confirm-dialog'
|
|
10
10
|
import type { Agent, Session } from '@/types'
|
|
@@ -58,7 +58,7 @@ export function AgentChatList({ inSidebar, onSelect }: Props) {
|
|
|
58
58
|
.filter(Boolean) as string[]
|
|
59
59
|
if (!sessionIds.length) { toast.error('No chats to delete'); return }
|
|
60
60
|
try {
|
|
61
|
-
await api('DELETE', '/
|
|
61
|
+
await api('DELETE', '/chats', { ids: sessionIds })
|
|
62
62
|
await loadSessions()
|
|
63
63
|
toast.success(`Deleted ${sessionIds.length} chat(s)`)
|
|
64
64
|
setBulkMode(false)
|
|
@@ -262,7 +262,7 @@ export function AgentChatList({ inSidebar, onSelect }: Props) {
|
|
|
262
262
|
const threadSession = agent.threadSessionId ? sessions[agent.threadSessionId] as Session | undefined : undefined
|
|
263
263
|
const lastMsg = threadSession?.messages?.at(-1)
|
|
264
264
|
const isActive = currentAgentId === agent.id
|
|
265
|
-
const heartbeatOn = agent.heartbeatEnabled === true && (agent.
|
|
265
|
+
const heartbeatOn = agent.heartbeatEnabled === true && (agent.plugins?.length ?? 0) > 0
|
|
266
266
|
const recentlyActive = (threadSession?.lastActiveAt ?? 0) > Date.now() - 30 * 60 * 1000
|
|
267
267
|
const isWorking = runningAgentIds.has(agent.id) || (threadSession?.active ?? false) || heartbeatOn || recentlyActive || chatroomActiveAgentIds.has(agent.id)
|
|
268
268
|
const isTyping = streamingSessionId === agent.threadSessionId
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState, useCallback } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import { api } from '@/lib/api-client'
|
|
6
5
|
import { AgentCard } from './agent-card'
|
|
7
6
|
import { TrashList } from './trash-list'
|
|
8
7
|
import { useApprovalStore } from '@/stores/use-approval-store'
|
|
@@ -17,8 +16,6 @@ export function AgentList({ inSidebar }: Props) {
|
|
|
17
16
|
const agents = useAppStore((s) => s.agents)
|
|
18
17
|
const loadAgents = useAppStore((s) => s.loadAgents)
|
|
19
18
|
const sessions = useAppStore((s) => s.sessions)
|
|
20
|
-
const currentUser = useAppStore((s) => s.currentUser)
|
|
21
|
-
const loadSessions = useAppStore((s) => s.loadSessions)
|
|
22
19
|
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
23
20
|
const activeProjectFilter = useAppStore((s) => s.activeProjectFilter)
|
|
24
21
|
const showTrash = useAppStore((s) => s.showTrash)
|
|
@@ -37,19 +34,17 @@ export function AgentList({ inSidebar }: Props) {
|
|
|
37
34
|
const currentSession = currentSessionId ? sessions[currentSessionId] : null
|
|
38
35
|
const selectedAgentId = currentSession?.agentId
|
|
39
36
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
const appSettings = useAppStore((s) => s.appSettings)
|
|
38
|
+
const updateSettings = useAppStore((s) => s.updateSettings)
|
|
39
|
+
const defaultAgentId = (appSettings.defaultAgentId && agents[appSettings.defaultAgentId])
|
|
40
|
+
? appSettings.defaultAgentId
|
|
41
|
+
: Object.values(agents)[0]?.id || 'default'
|
|
45
42
|
|
|
46
43
|
const handleSetDefault = useCallback(async (agentId: string) => {
|
|
47
|
-
if (!mainSession) return
|
|
48
44
|
try {
|
|
49
|
-
await
|
|
50
|
-
await loadSessions()
|
|
45
|
+
await updateSettings({ defaultAgentId: agentId })
|
|
51
46
|
} catch { /* ignore */ }
|
|
52
|
-
}, [
|
|
47
|
+
}, [updateSettings])
|
|
53
48
|
|
|
54
49
|
const [loaded, setLoaded] = useState(Object.keys(agents).length > 0)
|
|
55
50
|
useEffect(() => { loadAgents().then(() => setLoaded(true)) }, [])
|
|
@@ -75,7 +70,7 @@ export function AgentList({ inSidebar }: Props) {
|
|
|
75
70
|
const ids = new Set<string>()
|
|
76
71
|
const recentThreshold = now - 30 * 60 * 1000
|
|
77
72
|
for (const a of Object.values(agents)) {
|
|
78
|
-
if (a.heartbeatEnabled === true && (a.
|
|
73
|
+
if (a.heartbeatEnabled === true && (a.plugins?.length ?? 0) > 0) { ids.add(a.id); continue }
|
|
79
74
|
// Check if any session for this agent was active in the last 30 minutes
|
|
80
75
|
for (const s of Object.values(sessions)) {
|
|
81
76
|
if (s.agentId === a.id && (s.lastActiveAt ?? 0) > recentThreshold) { ids.add(a.id); break }
|
|
@@ -183,7 +183,7 @@ export function AgentSheet() {
|
|
|
183
183
|
setApiEndpoint(editing.apiEndpoint || null)
|
|
184
184
|
setIsOrchestrator(editing.isOrchestrator || false)
|
|
185
185
|
setAgentAgentIds(editing.subAgentIds || [])
|
|
186
|
-
setTools(editing.
|
|
186
|
+
setTools(editing.plugins || [])
|
|
187
187
|
setSkills(editing.skills || [])
|
|
188
188
|
setSkillIds(editing.skillIds || [])
|
|
189
189
|
setMcpServerIds(editing.mcpServerIds || [])
|
|
@@ -782,7 +782,7 @@ export function AgentSheet() {
|
|
|
782
782
|
</div>
|
|
783
783
|
</div>
|
|
784
784
|
)}
|
|
785
|
-
<p className="text-[11px] text-text-3/70 mt-1.5">Periodic check-in runs on idle
|
|
785
|
+
<p className="text-[11px] text-text-3/70 mt-1.5">Periodic check-in runs on idle chats using this agent. Processes pending events and monitors status.</p>
|
|
786
786
|
</div>
|
|
787
787
|
|
|
788
788
|
{/* Spend Limits */}
|
|
@@ -94,10 +94,10 @@ export function CronJobForm({ agentId, onSaved, onCancel }: Props) {
|
|
|
94
94
|
</select>
|
|
95
95
|
</div>
|
|
96
96
|
<div>
|
|
97
|
-
<label className="block text-[11px] font-600 uppercase tracking-wider text-text-3/50 mb-1">
|
|
97
|
+
<label className="block text-[11px] font-600 uppercase tracking-wider text-text-3/50 mb-1">Chat Target</label>
|
|
98
98
|
<select value={sessionTarget} onChange={(e) => setSessionTarget(e.target.value as typeof sessionTarget)} className={inputClass}>
|
|
99
|
-
<option value="main">Main
|
|
100
|
-
<option value="isolated">Isolated
|
|
99
|
+
<option value="main">Main chat</option>
|
|
100
|
+
<option value="isolated">Isolated chat</option>
|
|
101
101
|
</select>
|
|
102
102
|
</div>
|
|
103
103
|
</div>
|
|
@@ -171,11 +171,11 @@ function OverviewTab({ agent, onEditAgent, onClearHistory, onDeleteAgent, onDele
|
|
|
171
171
|
</div>
|
|
172
172
|
</div>
|
|
173
173
|
)}
|
|
174
|
-
{agent.
|
|
174
|
+
{agent.plugins && agent.plugins.length > 0 && (
|
|
175
175
|
<div>
|
|
176
176
|
<label className="block text-[11px] font-600 uppercase tracking-wider text-text-3/50 mb-1">Plugins</label>
|
|
177
177
|
<div className="flex flex-wrap gap-1">
|
|
178
|
-
{agent.
|
|
178
|
+
{agent.plugins.map((tool) => (
|
|
179
179
|
<span key={tool} className="px-2 py-0.5 rounded-[6px] text-[11px] font-600 bg-sky-400/[0.08] text-sky-400/70">
|
|
180
180
|
{tool}
|
|
181
181
|
</span>
|