@swarmclawai/swarmclaw 0.7.1 → 0.7.3
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 +155 -150
- package/package.json +1 -1
- package/src/app/api/agents/[id]/route.ts +26 -0
- package/src/app/api/agents/[id]/thread/route.ts +37 -9
- package/src/app/api/agents/route.ts +13 -2
- package/src/app/api/auth/route.ts +76 -7
- package/src/app/api/chatrooms/[id]/chat/route.ts +7 -2
- package/src/app/api/{sessions → chats}/[id]/browser/route.ts +5 -1
- package/src/app/api/{sessions → chats}/[id]/chat/route.ts +7 -3
- package/src/app/api/{sessions → chats}/[id]/checkpoints/route.ts +1 -1
- package/src/app/api/chats/[id]/main-loop/route.ts +13 -0
- package/src/app/api/{sessions → chats}/[id]/messages/route.ts +19 -13
- package/src/app/api/{sessions → chats}/[id]/restore/route.ts +1 -1
- package/src/app/api/{sessions → chats}/[id]/route.ts +22 -52
- package/src/app/api/{sessions → chats}/[id]/stop/route.ts +6 -1
- package/src/app/api/{sessions → chats}/route.ts +21 -7
- package/src/app/api/connectors/[id]/doctor/route.ts +26 -0
- package/src/app/api/connectors/doctor/route.ts +13 -0
- package/src/app/api/files/open/route.ts +16 -14
- package/src/app/api/memory/maintenance/route.ts +11 -1
- package/src/app/api/openclaw/agent-files/route.ts +27 -4
- package/src/app/api/openclaw/skills/route.ts +11 -3
- package/src/app/api/plugins/dependencies/route.ts +24 -0
- package/src/app/api/plugins/install/route.ts +15 -92
- package/src/app/api/plugins/route.ts +6 -26
- package/src/app/api/plugins/settings/route.ts +40 -0
- package/src/app/api/plugins/ui/route.ts +1 -0
- package/src/app/api/settings/route.ts +49 -7
- package/src/app/api/tasks/[id]/route.ts +15 -6
- package/src/app/api/tasks/bulk/route.ts +2 -2
- package/src/app/api/tasks/route.ts +9 -4
- package/src/app/api/usage/route.ts +30 -0
- package/src/app/api/webhooks/[id]/route.ts +8 -1
- package/src/app/page.tsx +9 -2
- package/src/cli/index.js +39 -33
- package/src/cli/index.ts +43 -49
- package/src/cli/spec.js +29 -27
- package/src/components/agents/agent-card.tsx +16 -13
- package/src/components/agents/agent-chat-list.tsx +104 -4
- package/src/components/agents/agent-list.tsx +54 -22
- package/src/components/agents/agent-sheet.tsx +209 -18
- package/src/components/agents/cron-job-form.tsx +3 -3
- package/src/components/agents/inspector-panel.tsx +110 -50
- package/src/components/auth/access-key-gate.tsx +36 -97
- package/src/components/auth/setup-wizard.tsx +5 -38
- package/src/components/chat/chat-area.tsx +39 -27
- package/src/components/{sessions/session-card.tsx → chat/chat-card.tsx} +7 -23
- package/src/components/chat/chat-header.tsx +299 -314
- package/src/components/{sessions/session-list.tsx → chat/chat-list.tsx} +11 -14
- 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 +5 -3
- 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/chatrooms/chatroom-view.tsx +347 -205
- package/src/components/connectors/connector-list.tsx +265 -127
- package/src/components/connectors/connector-sheet.tsx +218 -1
- package/src/components/home/home-view.tsx +129 -5
- package/src/components/layout/app-layout.tsx +392 -182
- package/src/components/layout/mobile-header.tsx +26 -8
- package/src/components/plugins/plugin-list.tsx +487 -254
- package/src/components/plugins/plugin-sheet.tsx +236 -13
- package/src/components/projects/project-detail.tsx +183 -0
- package/src/components/settings/gateway-connection-panel.tsx +1 -1
- package/src/components/shared/agent-picker-list.tsx +2 -2
- package/src/components/shared/command-palette.tsx +111 -25
- package/src/components/shared/settings/plugin-manager.tsx +20 -4
- package/src/components/shared/settings/section-capability-policy.tsx +105 -0
- package/src/components/shared/settings/section-heartbeat.tsx +78 -1
- package/src/components/shared/settings/section-orchestrator.tsx +3 -3
- package/src/components/shared/settings/section-providers.tsx +1 -1
- package/src/components/shared/settings/section-runtime-loop.tsx +5 -5
- package/src/components/shared/settings/section-secrets.tsx +6 -6
- package/src/components/shared/settings/section-user-preferences.tsx +1 -1
- package/src/components/shared/settings/section-voice.tsx +5 -1
- package/src/components/shared/settings/section-web-search.tsx +10 -2
- package/src/components/shared/settings/settings-page.tsx +244 -56
- package/src/components/tasks/approvals-panel.tsx +205 -18
- package/src/components/tasks/task-board.tsx +242 -46
- package/src/components/usage/metrics-dashboard.tsx +147 -1
- package/src/components/wallets/wallet-panel.tsx +17 -5
- package/src/components/webhooks/webhook-sheet.tsx +8 -8
- package/src/lib/auth.ts +17 -0
- package/src/lib/chat-streaming-state.test.ts +108 -0
- package/src/lib/chat-streaming-state.ts +108 -0
- package/src/lib/chat.ts +1 -1
- package/src/lib/{sessions.ts → chats.ts} +28 -18
- package/src/lib/openclaw-agent-id.test.ts +14 -0
- package/src/lib/openclaw-agent-id.ts +31 -0
- package/src/lib/providers/claude-cli.ts +1 -1
- package/src/lib/server/agent-assignment.test.ts +112 -0
- package/src/lib/server/agent-assignment.ts +169 -0
- package/src/lib/server/approval-connector-notify.test.ts +253 -0
- package/src/lib/server/approvals-auto-approve.test.ts +205 -0
- package/src/lib/server/approvals.ts +483 -75
- package/src/lib/server/autonomy-runtime.test.ts +341 -0
- package/src/lib/server/browser-state.test.ts +118 -0
- package/src/lib/server/browser-state.ts +123 -0
- package/src/lib/server/build-llm.test.ts +36 -0
- package/src/lib/server/build-llm.ts +11 -4
- package/src/lib/server/builtin-plugins.ts +34 -0
- package/src/lib/server/capability-router.ts +10 -8
- package/src/lib/server/chat-execution-heartbeat.test.ts +40 -0
- package/src/lib/server/chat-execution-tool-events.test.ts +134 -0
- package/src/lib/server/chat-execution.ts +285 -165
- package/src/lib/server/chatroom-health.test.ts +26 -0
- package/src/lib/server/chatroom-health.ts +2 -3
- package/src/lib/server/chatroom-helpers.test.ts +67 -2
- package/src/lib/server/chatroom-helpers.ts +48 -8
- package/src/lib/server/connectors/discord.ts +175 -11
- package/src/lib/server/connectors/doctor.test.ts +80 -0
- package/src/lib/server/connectors/doctor.ts +116 -0
- package/src/lib/server/connectors/manager.ts +948 -112
- package/src/lib/server/connectors/policy.test.ts +222 -0
- package/src/lib/server/connectors/policy.ts +452 -0
- package/src/lib/server/connectors/slack.ts +188 -9
- package/src/lib/server/connectors/telegram.ts +65 -15
- package/src/lib/server/connectors/thread-context.test.ts +44 -0
- package/src/lib/server/connectors/thread-context.ts +72 -0
- package/src/lib/server/connectors/types.ts +41 -11
- package/src/lib/server/cost.ts +34 -1
- package/src/lib/server/daemon-state.ts +61 -3
- package/src/lib/server/data-dir.ts +13 -0
- package/src/lib/server/delegation-jobs.test.ts +140 -0
- package/src/lib/server/delegation-jobs.ts +248 -0
- package/src/lib/server/document-utils.test.ts +47 -0
- package/src/lib/server/document-utils.ts +397 -0
- package/src/lib/server/heartbeat-service.ts +14 -40
- package/src/lib/server/heartbeat-source.test.ts +22 -0
- package/src/lib/server/heartbeat-source.ts +7 -0
- package/src/lib/server/identity-continuity.test.ts +77 -0
- package/src/lib/server/identity-continuity.ts +127 -0
- package/src/lib/server/mailbox-utils.ts +347 -0
- package/src/lib/server/main-agent-loop.ts +28 -1103
- package/src/lib/server/memory-db.ts +4 -6
- package/src/lib/server/memory-tiers.ts +40 -0
- package/src/lib/server/openclaw-agent-resolver.test.ts +70 -0
- package/src/lib/server/openclaw-agent-resolver.ts +128 -0
- package/src/lib/server/openclaw-exec-config.ts +5 -6
- package/src/lib/server/openclaw-skills-normalize.test.ts +56 -0
- package/src/lib/server/openclaw-skills-normalize.ts +136 -0
- package/src/lib/server/openclaw-sync.ts +3 -2
- package/src/lib/server/orchestrator-lg.ts +20 -9
- package/src/lib/server/orchestrator.ts +7 -7
- package/src/lib/server/playwright-proxy.mjs +27 -3
- package/src/lib/server/plugins.test.ts +207 -0
- package/src/lib/server/plugins.ts +927 -66
- package/src/lib/server/provider-health.ts +38 -6
- package/src/lib/server/queue.ts +13 -28
- package/src/lib/server/scheduler.ts +2 -0
- package/src/lib/server/session-archive-memory.test.ts +85 -0
- package/src/lib/server/session-archive-memory.ts +230 -0
- package/src/lib/server/session-mailbox.ts +8 -18
- package/src/lib/server/session-reset-policy.test.ts +99 -0
- package/src/lib/server/session-reset-policy.ts +311 -0
- package/src/lib/server/session-run-manager.ts +33 -82
- package/src/lib/server/session-tools/autonomy-tools.test.ts +105 -0
- package/src/lib/server/session-tools/calendar.ts +366 -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 +114 -10
- package/src/lib/server/session-tools/context.ts +21 -5
- package/src/lib/server/session-tools/crawl.ts +447 -0
- package/src/lib/server/session-tools/crud.ts +74 -28
- package/src/lib/server/session-tools/delegate-fallback.test.ts +219 -0
- package/src/lib/server/session-tools/delegate.ts +497 -24
- package/src/lib/server/session-tools/discovery.ts +24 -6
- package/src/lib/server/session-tools/document.ts +283 -0
- package/src/lib/server/session-tools/edit_file.ts +4 -2
- package/src/lib/server/session-tools/email.ts +320 -0
- package/src/lib/server/session-tools/extract.ts +137 -0
- package/src/lib/server/session-tools/file-normalize.test.ts +93 -0
- package/src/lib/server/session-tools/file-send.test.ts +84 -1
- package/src/lib/server/session-tools/file.ts +241 -25
- 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/human-loop.ts +227 -0
- package/src/lib/server/session-tools/image-gen.ts +380 -0
- package/src/lib/server/session-tools/index.ts +130 -50
- package/src/lib/server/session-tools/mailbox.ts +276 -0
- package/src/lib/server/session-tools/memory.ts +172 -3
- package/src/lib/server/session-tools/monitor.ts +151 -8
- package/src/lib/server/session-tools/normalize-tool-args.ts +17 -14
- 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-normalize.test.ts +142 -0
- package/src/lib/server/session-tools/platform.ts +148 -7
- package/src/lib/server/session-tools/plugin-creator.ts +89 -26
- package/src/lib/server/session-tools/primitive-tools.test.ts +257 -0
- package/src/lib/server/session-tools/replicate.ts +301 -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 +24 -12
- package/src/lib/server/session-tools/session-info.ts +43 -7
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +31 -17
- package/src/lib/server/session-tools/shell.ts +5 -2
- package/src/lib/server/session-tools/subagent.ts +194 -28
- package/src/lib/server/session-tools/table.ts +587 -0
- package/src/lib/server/session-tools/wallet.ts +42 -12
- package/src/lib/server/session-tools/web-browser-config.test.ts +39 -0
- package/src/lib/server/session-tools/web.ts +926 -91
- package/src/lib/server/storage.ts +255 -16
- package/src/lib/server/stream-agent-chat.ts +116 -268
- package/src/lib/server/structured-extract.test.ts +72 -0
- package/src/lib/server/structured-extract.ts +373 -0
- package/src/lib/server/task-mention.test.ts +16 -2
- package/src/lib/server/task-mention.ts +61 -10
- package/src/lib/server/tool-aliases.ts +66 -18
- package/src/lib/server/tool-capability-policy.test.ts +9 -9
- package/src/lib/server/tool-capability-policy.ts +38 -27
- package/src/lib/server/tool-retry.ts +2 -0
- package/src/lib/server/watch-jobs.test.ts +173 -0
- package/src/lib/server/watch-jobs.ts +532 -0
- package/src/lib/server/ws-hub.ts +5 -3
- package/src/lib/tool-definitions.ts +4 -0
- package/src/lib/validation/schemas.test.ts +26 -0
- package/src/lib/validation/schemas.ts +10 -1
- package/src/lib/ws-client.ts +14 -12
- package/src/proxy.ts +5 -5
- package/src/stores/use-app-store.ts +5 -11
- package/src/stores/use-chat-store.ts +38 -9
- package/src/types/index.ts +352 -47
- package/src/app/api/sessions/[id]/main-loop/route.ts +0 -94
- package/src/components/sessions/new-session-sheet.tsx +0 -253
- package/src/lib/server/main-session.ts +0 -24
- package/src/lib/server/session-run-manager.test.ts +0 -23
- /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]/retry/route.ts +0 -0
- /package/src/app/api/{sessions → chats}/heartbeat/route.ts +0 -0
|
@@ -6,8 +6,10 @@ import { useAppStore } from '@/stores/use-app-store'
|
|
|
6
6
|
interface CommandItem {
|
|
7
7
|
id: string
|
|
8
8
|
label: string
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
description?: string
|
|
10
|
+
keywords?: string[]
|
|
11
|
+
category: 'agent' | 'chat' | 'task' | 'nav' | 'setting'
|
|
12
|
+
onSelect: () => void | Promise<void>
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export function CommandPalette() {
|
|
@@ -20,13 +22,22 @@ export function CommandPalette() {
|
|
|
20
22
|
const agents = useAppStore((s) => s.agents)
|
|
21
23
|
const sessions = useAppStore((s) => s.sessions)
|
|
22
24
|
const tasks = useAppStore((s) => s.tasks)
|
|
25
|
+
const setCurrentAgent = useAppStore((s) => s.setCurrentAgent)
|
|
23
26
|
const setCurrentSession = useAppStore((s) => s.setCurrentSession)
|
|
24
27
|
const setActiveView = useAppStore((s) => s.setActiveView)
|
|
25
|
-
const setEditingAgentId = useAppStore((s) => s.setEditingAgentId)
|
|
26
|
-
const setAgentSheetOpen = useAppStore((s) => s.setAgentSheetOpen)
|
|
27
28
|
const setEditingTaskId = useAppStore((s) => s.setEditingTaskId)
|
|
28
29
|
const setTaskSheetOpen = useAppStore((s) => s.setTaskSheetOpen)
|
|
29
30
|
|
|
31
|
+
const openSettingsSection = useCallback((tabId?: string, sectionId?: string) => {
|
|
32
|
+
setActiveView('settings')
|
|
33
|
+
setOpen(false)
|
|
34
|
+
window.setTimeout(() => {
|
|
35
|
+
window.dispatchEvent(new CustomEvent('swarmclaw:settings-focus', {
|
|
36
|
+
detail: { tabId, sectionId },
|
|
37
|
+
}))
|
|
38
|
+
}, 80)
|
|
39
|
+
}, [setActiveView])
|
|
40
|
+
|
|
30
41
|
// Register keyboard shortcut
|
|
31
42
|
useEffect(() => {
|
|
32
43
|
const handler = (e: KeyboardEvent) => {
|
|
@@ -54,33 +65,89 @@ export function CommandPalette() {
|
|
|
54
65
|
const items = useMemo<CommandItem[]>(() => {
|
|
55
66
|
const result: CommandItem[] = []
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
const views = [
|
|
69
|
+
{ id: 'home', label: 'Home', description: 'Overview and triage', keywords: ['dashboard', 'overview', 'activity'] },
|
|
70
|
+
{ id: 'agents', label: 'Agents', description: 'Agent chats and configuration', keywords: ['chat', 'assistant', 'default'] },
|
|
71
|
+
{ id: 'tasks', label: 'Tasks', description: 'Task board and approvals', keywords: ['board', 'queue', 'backlog', 'approval'] },
|
|
72
|
+
{ id: 'projects', label: 'Projects', description: 'Scoped workspaces for agents and tasks', keywords: ['workspace', 'scope'] },
|
|
73
|
+
{ id: 'chatrooms', label: 'Chatrooms', description: 'Shared multi-agent conversations', keywords: ['group', 'room', 'mentions'] },
|
|
74
|
+
{ id: 'schedules', label: 'Schedules', description: 'Recurring and timed automations', keywords: ['cron', 'automation', 'interval'] },
|
|
75
|
+
{ id: 'connectors', label: 'Connectors', description: 'Bridges to Slack, Discord, Telegram, and more', keywords: ['discord', 'slack', 'telegram', 'whatsapp'] },
|
|
76
|
+
{ id: 'memory', label: 'Memory', description: 'Stored agent memory and retrieval', keywords: ['knowledge', 'vector', 'retrieval'] },
|
|
77
|
+
{ id: 'knowledge', label: 'Knowledge', description: 'Shared knowledge base', keywords: ['docs', 'entries', 'facts'] },
|
|
78
|
+
{ id: 'providers', label: 'Providers', description: 'Model providers and endpoints', keywords: ['openai', 'anthropic', 'ollama', 'endpoint'] },
|
|
79
|
+
{ id: 'secrets', label: 'Secrets', description: 'Credentials and encrypted secrets', keywords: ['api key', 'token', 'credential'] },
|
|
80
|
+
{ id: 'settings', label: 'Settings', description: 'General app configuration', keywords: ['preferences', 'theme', 'heartbeat'] },
|
|
81
|
+
] as const
|
|
82
|
+
for (const view of views) {
|
|
60
83
|
result.push({
|
|
61
|
-
id: `nav:${
|
|
62
|
-
label: `Go to ${
|
|
84
|
+
id: `nav:${view.id}`,
|
|
85
|
+
label: `Go to ${view.label}`,
|
|
86
|
+
description: view.description,
|
|
87
|
+
keywords: [...view.keywords],
|
|
63
88
|
category: 'nav',
|
|
64
|
-
onSelect: () => { setActiveView(
|
|
89
|
+
onSelect: () => { setActiveView(view.id); setOpen(false) },
|
|
65
90
|
})
|
|
66
91
|
}
|
|
67
92
|
|
|
68
|
-
|
|
93
|
+
result.push(
|
|
94
|
+
{
|
|
95
|
+
id: 'setting:default-agent',
|
|
96
|
+
label: 'Default Agent Shortcut',
|
|
97
|
+
description: 'Choose which agent the sidebar shortcut opens',
|
|
98
|
+
keywords: ['main chat', 'default agent', 'shortcut'],
|
|
99
|
+
category: 'setting',
|
|
100
|
+
onSelect: () => openSettingsSection('general', 'user-preferences'),
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: 'setting:automation',
|
|
104
|
+
label: 'Automation Limits',
|
|
105
|
+
description: 'Heartbeat, autonomy, and delegation controls',
|
|
106
|
+
keywords: ['loops', 'coordination', 'delegation', 'heartbeat', 'automation'],
|
|
107
|
+
category: 'setting',
|
|
108
|
+
onSelect: () => openSettingsSection('agents', 'runtime-loop'),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'setting:providers',
|
|
112
|
+
label: 'Provider Credentials',
|
|
113
|
+
description: 'Manage providers, endpoints, and secrets',
|
|
114
|
+
keywords: ['openai', 'anthropic', 'api keys', 'credentials', 'providers'],
|
|
115
|
+
category: 'setting',
|
|
116
|
+
onSelect: () => openSettingsSection('integrations', 'providers'),
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'setting:voice',
|
|
120
|
+
label: 'Voice & Search',
|
|
121
|
+
description: 'Voice output and web search defaults',
|
|
122
|
+
keywords: ['voice', 'tts', 'web search', 'search'],
|
|
123
|
+
category: 'setting',
|
|
124
|
+
onSelect: () => openSettingsSection('memory', 'voice'),
|
|
125
|
+
},
|
|
126
|
+
)
|
|
127
|
+
|
|
69
128
|
for (const agent of Object.values(agents)) {
|
|
70
129
|
result.push({
|
|
71
130
|
id: `agent:${agent.id}`,
|
|
72
131
|
label: agent.name,
|
|
132
|
+
description: `Open ${agent.name}'s chat`,
|
|
133
|
+
keywords: [agent.provider, agent.model, agent.description || ''].filter(Boolean),
|
|
73
134
|
category: 'agent',
|
|
74
|
-
onSelect: () => {
|
|
135
|
+
onSelect: async () => {
|
|
136
|
+
await setCurrentAgent(agent.id)
|
|
137
|
+
setActiveView('agents')
|
|
138
|
+
setOpen(false)
|
|
139
|
+
},
|
|
75
140
|
})
|
|
76
141
|
}
|
|
77
142
|
|
|
78
143
|
// Chats (sessions)
|
|
79
144
|
for (const session of Object.values(sessions)) {
|
|
80
|
-
|
|
145
|
+
const sessionAgent = session.agentId ? agents[session.agentId] : null
|
|
81
146
|
result.push({
|
|
82
147
|
id: `chat:${session.id}`,
|
|
83
148
|
label: session.name || 'Untitled chat',
|
|
149
|
+
description: sessionAgent ? `Recent chat with ${sessionAgent.name}` : 'Direct model chat',
|
|
150
|
+
keywords: [session.provider, session.model, sessionAgent?.name || ''].filter(Boolean),
|
|
84
151
|
category: 'chat',
|
|
85
152
|
onSelect: () => { setCurrentSession(session.id); setActiveView('agents'); setOpen(false) },
|
|
86
153
|
})
|
|
@@ -92,19 +159,25 @@ export function CommandPalette() {
|
|
|
92
159
|
result.push({
|
|
93
160
|
id: `task:${task.id}`,
|
|
94
161
|
label: task.title,
|
|
162
|
+
description: `${task.status.charAt(0).toUpperCase() + task.status.slice(1)} task`,
|
|
163
|
+
keywords: [task.status, task.agentId || ''].filter(Boolean),
|
|
95
164
|
category: 'task',
|
|
96
165
|
onSelect: () => { setEditingTaskId(task.id); setTaskSheetOpen(true); setOpen(false) },
|
|
97
166
|
})
|
|
98
167
|
}
|
|
99
168
|
|
|
100
169
|
return result
|
|
101
|
-
}, [agents,
|
|
170
|
+
}, [agents, openSettingsSection, sessions, setActiveView, setCurrentAgent, setCurrentSession, setEditingTaskId, setTaskSheetOpen, tasks])
|
|
102
171
|
|
|
103
172
|
const filtered = useMemo(() => {
|
|
104
173
|
if (!query.trim()) return items.slice(0, 20)
|
|
105
174
|
const q = query.toLowerCase()
|
|
106
175
|
return items
|
|
107
|
-
.filter((item) =>
|
|
176
|
+
.filter((item) =>
|
|
177
|
+
item.label.toLowerCase().includes(q)
|
|
178
|
+
|| item.description?.toLowerCase().includes(q)
|
|
179
|
+
|| item.keywords?.some((keyword) => keyword.toLowerCase().includes(q)),
|
|
180
|
+
)
|
|
108
181
|
.slice(0, 20)
|
|
109
182
|
}, [items, query])
|
|
110
183
|
|
|
@@ -133,7 +206,7 @@ export function CommandPalette() {
|
|
|
133
206
|
|
|
134
207
|
if (!open) return null
|
|
135
208
|
|
|
136
|
-
const categoryLabel = { agent: 'Agents', chat: 'Chats', task: 'Tasks', nav: 'Navigation' } as const
|
|
209
|
+
const categoryLabel = { agent: 'Agents', chat: 'Chats', task: 'Tasks', nav: 'Navigation', setting: 'Settings' } as const
|
|
137
210
|
const categoryIcon = {
|
|
138
211
|
agent: (
|
|
139
212
|
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
@@ -155,6 +228,12 @@ export function CommandPalette() {
|
|
|
155
228
|
<circle cx="11" cy="11" r="8" /><line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
156
229
|
</svg>
|
|
157
230
|
),
|
|
231
|
+
setting: (
|
|
232
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
233
|
+
<circle cx="12" cy="12" r="3" />
|
|
234
|
+
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
235
|
+
</svg>
|
|
236
|
+
),
|
|
158
237
|
}
|
|
159
238
|
|
|
160
239
|
// Group by category
|
|
@@ -184,14 +263,14 @@ export function CommandPalette() {
|
|
|
184
263
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="text-text-3 shrink-0 relative z-10">
|
|
185
264
|
<circle cx="11" cy="11" r="8" /><line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
186
265
|
</svg>
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
266
|
+
<input
|
|
267
|
+
ref={inputRef}
|
|
268
|
+
value={query}
|
|
269
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
270
|
+
onKeyDown={handleKeyDown}
|
|
271
|
+
placeholder="Search chats, agents, tasks, settings..."
|
|
272
|
+
className="flex-1 bg-transparent border-none outline-none text-[14px] text-text-1 placeholder:text-text-3/50"
|
|
273
|
+
/>
|
|
195
274
|
<kbd className="hidden md:inline-flex items-center px-1.5 py-0.5 rounded-[6px] bg-white/[0.06] text-[11px] text-text-3 font-500">
|
|
196
275
|
esc
|
|
197
276
|
</kbd>
|
|
@@ -221,7 +300,14 @@ export function CommandPalette() {
|
|
|
221
300
|
<div className="absolute left-0 top-1 bottom-1 w-1 rounded-r-full bg-accent-bright" style={{ animation: 'spring-in 0.3s var(--ease-spring)' }} />
|
|
222
301
|
)}
|
|
223
302
|
<span className="shrink-0 text-text-3">{categoryIcon[item.category as keyof typeof categoryIcon]}</span>
|
|
224
|
-
<
|
|
303
|
+
<div className="min-w-0 flex-1">
|
|
304
|
+
<div className="text-[13px] font-500 truncate">{item.label}</div>
|
|
305
|
+
{item.description && (
|
|
306
|
+
<div className={`text-[11px] truncate ${idx === selectedIndex ? 'text-accent-bright/75' : 'text-text-3/55'}`}>
|
|
307
|
+
{item.description}
|
|
308
|
+
</div>
|
|
309
|
+
)}
|
|
310
|
+
</div>
|
|
225
311
|
</button>
|
|
226
312
|
)
|
|
227
313
|
})}
|
|
@@ -129,8 +129,8 @@ export function PluginManager() {
|
|
|
129
129
|
|
|
130
130
|
const { corePlugins, installedPlugins } = useMemo(() => {
|
|
131
131
|
return {
|
|
132
|
-
corePlugins: plugins.filter(p => p.
|
|
133
|
-
installedPlugins: plugins.filter(p => p.
|
|
132
|
+
corePlugins: plugins.filter(p => p.isBuiltin),
|
|
133
|
+
installedPlugins: plugins.filter(p => !p.isBuiltin)
|
|
134
134
|
}
|
|
135
135
|
}, [plugins])
|
|
136
136
|
|
|
@@ -155,6 +155,22 @@ export function PluginManager() {
|
|
|
155
155
|
</div>
|
|
156
156
|
<div className="text-[11px] font-mono text-text-3/40 truncate">{p.filename}</div>
|
|
157
157
|
{p.description && <div className="text-[12px] text-text-3/70 mt-1 line-clamp-1">{p.description}</div>}
|
|
158
|
+
{p.hasDependencyManifest && (
|
|
159
|
+
<div className="mt-1.5 flex items-center gap-2 text-[10px] font-700 uppercase tracking-[0.08em]">
|
|
160
|
+
<span className="px-1.5 py-0.5 rounded bg-white/[0.04] text-text-3/70">
|
|
161
|
+
{p.dependencyCount ?? 0} deps
|
|
162
|
+
</span>
|
|
163
|
+
<span className={`px-1.5 py-0.5 rounded ${
|
|
164
|
+
p.dependencyInstallStatus === 'installed'
|
|
165
|
+
? 'bg-emerald-500/10 text-emerald-400'
|
|
166
|
+
: p.dependencyInstallStatus === 'error'
|
|
167
|
+
? 'bg-red-500/10 text-red-400'
|
|
168
|
+
: 'bg-amber-500/10 text-amber-400'
|
|
169
|
+
}`}>
|
|
170
|
+
{p.dependencyInstallStatus || 'ready'}
|
|
171
|
+
</span>
|
|
172
|
+
</div>
|
|
173
|
+
)}
|
|
158
174
|
{p.autoDisabled && (
|
|
159
175
|
<div className="text-[11px] text-amber-400/90 mt-1.5 p-2 rounded-[8px] bg-amber-500/[0.03] border border-amber-500/10">
|
|
160
176
|
{p.lastFailureStage ? `Error at ${p.lastFailureStage}:` : 'Last error:'} {p.lastFailureError}
|
|
@@ -163,7 +179,7 @@ export function PluginManager() {
|
|
|
163
179
|
</div>
|
|
164
180
|
|
|
165
181
|
<div className="flex items-center gap-2">
|
|
166
|
-
{p.
|
|
182
|
+
{!p.isBuiltin && (
|
|
167
183
|
<div className="flex items-center opacity-0 group-hover:opacity-100 transition-opacity">
|
|
168
184
|
<button
|
|
169
185
|
onClick={() => handleUpdateOne(p.filename)}
|
|
@@ -409,7 +425,7 @@ export function PluginManager() {
|
|
|
409
425
|
</div>
|
|
410
426
|
)}
|
|
411
427
|
<p className="text-[11px] text-text-3/40 mt-6 leading-relaxed text-center italic">
|
|
412
|
-
SwarmClaw supports
|
|
428
|
+
SwarmClaw supports `.js` / `.mjs` plugins, native SwarmClaw hooks/tools, and OpenClaw activate/register formats.
|
|
413
429
|
</p>
|
|
414
430
|
</div>
|
|
415
431
|
)}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
+
import type { ApprovalCategory } from '@/types'
|
|
3
4
|
import type { SettingsSectionProps } from './types'
|
|
4
5
|
|
|
6
|
+
const APPROVAL_CATEGORY_OPTIONS: Array<{ id: ApprovalCategory; label: string; description: string }> = [
|
|
7
|
+
{ id: 'tool_access', label: 'Plugin Access', description: 'Auto-enable requested plugins for a chat.' },
|
|
8
|
+
{ id: 'plugin_scaffold', label: 'Plugin Scaffold', description: 'Auto-create plugin files requested by agents.' },
|
|
9
|
+
{ id: 'plugin_install', label: 'Plugin Install', description: 'Auto-install plugins from approved URLs.' },
|
|
10
|
+
{ id: 'human_loop', label: 'Human Approval Requests', description: 'Auto-approve ask-human approval prompts.' },
|
|
11
|
+
{ id: 'wallet_transfer', label: 'Wallet Transfers', description: 'Auto-approve wallet send requests. High risk.' },
|
|
12
|
+
{ id: 'task_tool', label: 'Task Tool Calls', description: 'Reserved for task-level approval flows.' },
|
|
13
|
+
]
|
|
14
|
+
|
|
5
15
|
export function CapabilityPolicySection({ appSettings, patchSettings, inputClass }: SettingsSectionProps) {
|
|
16
|
+
const autoApproved = new Set(appSettings.approvalAutoApproveCategories || [])
|
|
17
|
+
|
|
6
18
|
return (
|
|
7
19
|
<div className="mb-10">
|
|
8
20
|
<h3 className="font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-2">
|
|
@@ -34,6 +46,24 @@ export function CapabilityPolicySection({ appSettings, patchSettings, inputClass
|
|
|
34
46
|
</div>
|
|
35
47
|
|
|
36
48
|
<div className="grid grid-cols-1 gap-4">
|
|
49
|
+
<div className="rounded-[12px] border border-white/[0.06] bg-bg px-4 py-4">
|
|
50
|
+
<div className="flex items-center justify-between gap-4">
|
|
51
|
+
<div>
|
|
52
|
+
<div className="text-[12px] font-600 text-text-2">Platform Approvals</div>
|
|
53
|
+
<p className="text-[11px] text-text-3/60 mt-1 leading-relaxed">
|
|
54
|
+
Turn this off to auto-approve every approval request across the platform for maximum autonomy. Audit records are still kept.
|
|
55
|
+
</p>
|
|
56
|
+
</div>
|
|
57
|
+
<button
|
|
58
|
+
onClick={() => patchSettings({ approvalsEnabled: !(appSettings.approvalsEnabled ?? true) })}
|
|
59
|
+
className={`relative w-10 h-[22px] rounded-full transition-colors duration-200 cursor-pointer ${(appSettings.approvalsEnabled ?? true) ? 'bg-accent' : 'bg-white/[0.12]'}`}
|
|
60
|
+
aria-label="Toggle platform approvals"
|
|
61
|
+
>
|
|
62
|
+
<span className={`absolute top-[3px] left-[3px] w-4 h-4 rounded-full bg-white transition-transform duration-200 ${(appSettings.approvalsEnabled ?? true) ? 'translate-x-[18px]' : ''}`} />
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
37
67
|
<div>
|
|
38
68
|
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Blocked Categories</label>
|
|
39
69
|
<input
|
|
@@ -86,6 +116,81 @@ export function CapabilityPolicySection({ appSettings, patchSettings, inputClass
|
|
|
86
116
|
/>
|
|
87
117
|
<p className="text-[11px] text-text-3/60 mt-2">Use this to re-allow specific tool families when running in strict mode.</p>
|
|
88
118
|
</div>
|
|
119
|
+
|
|
120
|
+
<div>
|
|
121
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Auto-Approve Workflow Requests</label>
|
|
122
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
|
|
123
|
+
{APPROVAL_CATEGORY_OPTIONS.map((option) => {
|
|
124
|
+
const checked = autoApproved.has(option.id)
|
|
125
|
+
return (
|
|
126
|
+
<label
|
|
127
|
+
key={option.id}
|
|
128
|
+
className={`rounded-[12px] border px-3 py-3 cursor-pointer transition-all ${
|
|
129
|
+
checked
|
|
130
|
+
? 'border-accent-bright/30 bg-accent-soft/60'
|
|
131
|
+
: 'border-white/[0.06] bg-bg hover:bg-surface-2'
|
|
132
|
+
}`}
|
|
133
|
+
>
|
|
134
|
+
<div className="flex items-start gap-3">
|
|
135
|
+
<input
|
|
136
|
+
type="checkbox"
|
|
137
|
+
checked={checked}
|
|
138
|
+
onChange={(e) => {
|
|
139
|
+
const next = new Set(appSettings.approvalAutoApproveCategories || [])
|
|
140
|
+
if (e.target.checked) next.add(option.id)
|
|
141
|
+
else next.delete(option.id)
|
|
142
|
+
patchSettings({ approvalAutoApproveCategories: [...next] })
|
|
143
|
+
}}
|
|
144
|
+
className="mt-0.5"
|
|
145
|
+
/>
|
|
146
|
+
<div>
|
|
147
|
+
<div className="text-[12px] font-600 text-text-2">{option.label}</div>
|
|
148
|
+
<p className="text-[11px] text-text-3/60 mt-1 leading-relaxed">{option.description}</p>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</label>
|
|
152
|
+
)
|
|
153
|
+
})}
|
|
154
|
+
</div>
|
|
155
|
+
<p className="text-[11px] text-text-3/60 mt-2">
|
|
156
|
+
Auto-approved categories execute immediately instead of waiting in the Approvals queue. Leave high-risk categories off unless the user explicitly wants fully autonomous execution.
|
|
157
|
+
</p>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<div className="rounded-[12px] border border-white/[0.06] bg-bg px-4 py-4">
|
|
161
|
+
<div className="flex items-center justify-between gap-4">
|
|
162
|
+
<div>
|
|
163
|
+
<div className="text-[12px] font-600 text-text-2">Connector Approval Reminders</div>
|
|
164
|
+
<p className="text-[11px] text-text-3/60 mt-1 leading-relaxed">
|
|
165
|
+
If an approval sits too long, let the agent send a one-time reminder over an active connector conversation it already has access to.
|
|
166
|
+
</p>
|
|
167
|
+
</div>
|
|
168
|
+
<button
|
|
169
|
+
onClick={() => patchSettings({ approvalConnectorNotifyEnabled: !(appSettings.approvalConnectorNotifyEnabled ?? true) })}
|
|
170
|
+
className={`relative w-10 h-[22px] rounded-full transition-colors duration-200 cursor-pointer ${(appSettings.approvalConnectorNotifyEnabled ?? true) ? 'bg-accent' : 'bg-white/[0.12]'}`}
|
|
171
|
+
aria-label="Toggle connector approval reminders"
|
|
172
|
+
>
|
|
173
|
+
<span className={`absolute top-[3px] left-[3px] w-4 h-4 rounded-full bg-white transition-transform duration-200 ${(appSettings.approvalConnectorNotifyEnabled ?? true) ? 'translate-x-[18px]' : ''}`} />
|
|
174
|
+
</button>
|
|
175
|
+
</div>
|
|
176
|
+
<div className="mt-4 max-w-[220px]">
|
|
177
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Reminder Delay (Sec)</label>
|
|
178
|
+
<input
|
|
179
|
+
type="number"
|
|
180
|
+
min={30}
|
|
181
|
+
max={86400}
|
|
182
|
+
value={appSettings.approvalConnectorNotifyDelaySec ?? 300}
|
|
183
|
+
onChange={(e) => {
|
|
184
|
+
const next = Number.parseInt(e.target.value, 10)
|
|
185
|
+
patchSettings({
|
|
186
|
+
approvalConnectorNotifyDelaySec: Number.isFinite(next) ? Math.max(30, Math.min(86400, next)) : 300,
|
|
187
|
+
})
|
|
188
|
+
}}
|
|
189
|
+
className={inputClass}
|
|
190
|
+
style={{ fontFamily: 'inherit' }}
|
|
191
|
+
/>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
89
194
|
</div>
|
|
90
195
|
</div>
|
|
91
196
|
</div>
|
|
@@ -3,12 +3,17 @@
|
|
|
3
3
|
import { useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
5
|
import { api } from '@/lib/api-client'
|
|
6
|
+
import type { SessionResetMode } from '@/types'
|
|
6
7
|
import type { SettingsSectionProps } from './types'
|
|
7
8
|
|
|
8
9
|
export function HeartbeatSection({ appSettings, patchSettings, inputClass }: SettingsSectionProps) {
|
|
9
10
|
const loadSessions = useAppStore((s) => s.loadSessions)
|
|
10
11
|
const [disablingHeartbeats, setDisablingHeartbeats] = useState(false)
|
|
11
12
|
const [heartbeatBulkNotice, setHeartbeatBulkNotice] = useState('')
|
|
13
|
+
const parseResetMode = (value: string): SessionResetMode | null => {
|
|
14
|
+
if (value === 'idle' || value === 'daily') return value
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
12
17
|
|
|
13
18
|
const handleDisableAllHeartbeats = async () => {
|
|
14
19
|
if (disablingHeartbeats) return
|
|
@@ -20,7 +25,7 @@ export function HeartbeatSection({ appSettings, patchSettings, inputClass }: Set
|
|
|
20
25
|
updatedSessions: number
|
|
21
26
|
cancelledQueued: number
|
|
22
27
|
abortedRunning: number
|
|
23
|
-
}>('POST', '/
|
|
28
|
+
}>('POST', '/chats/heartbeat', { action: 'disable_all' })
|
|
24
29
|
await loadSessions()
|
|
25
30
|
setHeartbeatBulkNotice(
|
|
26
31
|
`Stopped heartbeat on ${result.updatedSessions} session(s); cancelled ${result.cancelledQueued} queued run(s), aborted ${result.abortedRunning} running run(s).`,
|
|
@@ -112,6 +117,78 @@ export function HeartbeatSection({ appSettings, patchSettings, inputClass }: Set
|
|
|
112
117
|
</div>
|
|
113
118
|
</div>
|
|
114
119
|
|
|
120
|
+
<div className="border-t border-white/[0.06] pt-5 mt-5">
|
|
121
|
+
<h4 className="font-display text-[11px] font-600 text-text-2 uppercase tracking-[0.08em] mb-2">
|
|
122
|
+
Session Reset Defaults
|
|
123
|
+
</h4>
|
|
124
|
+
<p className="text-[11px] text-text-3/60 mb-4">
|
|
125
|
+
Freshness policy inherited by new sessions unless overridden on the agent or session itself.
|
|
126
|
+
</p>
|
|
127
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 mb-3">
|
|
128
|
+
<div>
|
|
129
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Reset Mode</label>
|
|
130
|
+
<select
|
|
131
|
+
value={appSettings.sessionResetMode || ''}
|
|
132
|
+
onChange={(e) => patchSettings({ sessionResetMode: parseResetMode(e.target.value) })}
|
|
133
|
+
className={inputClass}
|
|
134
|
+
style={{ fontFamily: 'inherit' }}
|
|
135
|
+
>
|
|
136
|
+
<option value="">Use built-in defaults</option>
|
|
137
|
+
<option value="idle">Idle</option>
|
|
138
|
+
<option value="daily">Daily</option>
|
|
139
|
+
</select>
|
|
140
|
+
</div>
|
|
141
|
+
<div>
|
|
142
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Idle Timeout (sec)</label>
|
|
143
|
+
<input
|
|
144
|
+
type="number"
|
|
145
|
+
min={0}
|
|
146
|
+
value={appSettings.sessionIdleTimeoutSec ?? ''}
|
|
147
|
+
onChange={(e) => patchSettings({ sessionIdleTimeoutSec: e.target.value ? Number.parseInt(e.target.value, 10) : null })}
|
|
148
|
+
placeholder="43200"
|
|
149
|
+
className={inputClass}
|
|
150
|
+
style={{ fontFamily: 'inherit' }}
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
|
|
155
|
+
<div>
|
|
156
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Max Age (sec)</label>
|
|
157
|
+
<input
|
|
158
|
+
type="number"
|
|
159
|
+
min={0}
|
|
160
|
+
value={appSettings.sessionMaxAgeSec ?? ''}
|
|
161
|
+
onChange={(e) => patchSettings({ sessionMaxAgeSec: e.target.value ? Number.parseInt(e.target.value, 10) : null })}
|
|
162
|
+
placeholder="604800"
|
|
163
|
+
className={inputClass}
|
|
164
|
+
style={{ fontFamily: 'inherit' }}
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
<div>
|
|
168
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Daily Reset Time</label>
|
|
169
|
+
<input
|
|
170
|
+
type="text"
|
|
171
|
+
value={appSettings.sessionDailyResetAt || ''}
|
|
172
|
+
onChange={(e) => patchSettings({ sessionDailyResetAt: e.target.value || null })}
|
|
173
|
+
placeholder="04:00"
|
|
174
|
+
className={inputClass}
|
|
175
|
+
style={{ fontFamily: 'inherit' }}
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
178
|
+
<div>
|
|
179
|
+
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Reset Timezone</label>
|
|
180
|
+
<input
|
|
181
|
+
type="text"
|
|
182
|
+
value={appSettings.sessionResetTimezone || ''}
|
|
183
|
+
onChange={(e) => patchSettings({ sessionResetTimezone: e.target.value || null })}
|
|
184
|
+
placeholder="UTC"
|
|
185
|
+
className={inputClass}
|
|
186
|
+
style={{ fontFamily: 'inherit' }}
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
115
192
|
<div>
|
|
116
193
|
<div className="flex items-center gap-2.5">
|
|
117
194
|
<button
|
|
@@ -27,10 +27,10 @@ export function OrchestratorSection({ appSettings, patchSettings, inputClass }:
|
|
|
27
27
|
return (
|
|
28
28
|
<div className="mb-10">
|
|
29
29
|
<h3 className="font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-2">
|
|
30
|
-
|
|
30
|
+
Coordination Engine
|
|
31
31
|
</h3>
|
|
32
32
|
<p className="text-[12px] text-text-3 mb-5">
|
|
33
|
-
The LLM provider used
|
|
33
|
+
The LLM provider used when agents coordinate delegation, tool calling, and automation-heavy runs.
|
|
34
34
|
</p>
|
|
35
35
|
|
|
36
36
|
<div className="p-6 rounded-[18px] bg-surface border border-white/[0.06]">
|
|
@@ -53,7 +53,7 @@ export function OrchestratorSection({ appSettings, patchSettings, inputClass }:
|
|
|
53
53
|
</div>
|
|
54
54
|
{lgProviders.length === 0 && (
|
|
55
55
|
<p className="text-[12px] text-text-3/60 mb-5">
|
|
56
|
-
No
|
|
56
|
+
No coordination-compatible providers available. Add an API provider in Providers.
|
|
57
57
|
</p>
|
|
58
58
|
)}
|
|
59
59
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState } from 'react'
|
|
4
4
|
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
-
import { createCredential, deleteCredential } from '@/lib/
|
|
5
|
+
import { createCredential, deleteCredential } from '@/lib/chats'
|
|
6
6
|
import { toast } from 'sonner'
|
|
7
7
|
import type { ProviderType } from '@/types'
|
|
8
8
|
import type { SettingsSectionProps } from './types'
|
|
@@ -24,7 +24,7 @@ export function RuntimeLoopSection({ appSettings, patchSettings, inputClass }: S
|
|
|
24
24
|
Runtime & Loop Controls
|
|
25
25
|
</h3>
|
|
26
26
|
<p className="text-[12px] text-text-3 mb-5">
|
|
27
|
-
|
|
27
|
+
Control how far agents can run on their own and set safety guards for delegation and tool execution.
|
|
28
28
|
</p>
|
|
29
29
|
<div className="p-6 rounded-[18px] bg-surface border border-white/[0.06]">
|
|
30
30
|
<label className="flex items-center gap-1.5 font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-3">Loop Mode <HintTip text="Bounded = fixed max steps. Ongoing = runs until the task completes (with a safety cap)" /></label>
|
|
@@ -64,8 +64,8 @@ export function RuntimeLoopSection({ appSettings, patchSettings, inputClass }: S
|
|
|
64
64
|
style={{ fontFamily: 'inherit' }}
|
|
65
65
|
/>
|
|
66
66
|
</div>
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
<div>
|
|
68
|
+
<label className="flex items-center gap-1.5 font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Coordination Steps <HintTip text="Maximum tool calls an agent can make while coordinating multiple delegated agents" /></label>
|
|
69
69
|
<input
|
|
70
70
|
type="number"
|
|
71
71
|
min={1}
|
|
@@ -79,8 +79,8 @@ export function RuntimeLoopSection({ appSettings, patchSettings, inputClass }: S
|
|
|
79
79
|
style={{ fontFamily: 'inherit' }}
|
|
80
80
|
/>
|
|
81
81
|
</div>
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
<div>
|
|
83
|
+
<label className="flex items-center gap-1.5 font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Legacy Turns <HintTip text="Compatibility limit for older coordination flows that still rely on turn-based execution" /></label>
|
|
84
84
|
<input
|
|
85
85
|
type="number"
|
|
86
86
|
min={1}
|
|
@@ -53,7 +53,7 @@ export function SecretsSection({ appSettings, inputClass }: SettingsSectionProps
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const
|
|
56
|
+
const selectableAgents = Object.values(agents)
|
|
57
57
|
const secretList = Object.entries(secrets).map(([rowId, secret]) => ({ ...secret, rowId }))
|
|
58
58
|
|
|
59
59
|
return (
|
|
@@ -62,7 +62,7 @@ export function SecretsSection({ appSettings, inputClass }: SettingsSectionProps
|
|
|
62
62
|
Service Credentials
|
|
63
63
|
</h3>
|
|
64
64
|
<p className="text-[12px] text-text-3 mb-5">
|
|
65
|
-
Credentials for external services (Gmail, APIs, etc.) that
|
|
65
|
+
Credentials for external services (Gmail, APIs, etc.) that agents can use during task execution.
|
|
66
66
|
</p>
|
|
67
67
|
|
|
68
68
|
{secretList.length > 0 && (
|
|
@@ -78,7 +78,7 @@ export function SecretsSection({ appSettings, inputClass }: SettingsSectionProps
|
|
|
78
78
|
? 'bg-emerald-500/10 text-emerald-400'
|
|
79
79
|
: 'bg-amber-500/10 text-amber-400'
|
|
80
80
|
}`}>
|
|
81
|
-
{secret.scope === 'global' ? 'All
|
|
81
|
+
{secret.scope === 'global' ? 'All eligible agents' : `${secret.agentIds.length} agent(s)`}
|
|
82
82
|
</span>
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
@@ -106,14 +106,14 @@ export function SecretsSection({ appSettings, inputClass }: SettingsSectionProps
|
|
|
106
106
|
<label className="block font-display text-[11px] font-600 text-text-3 uppercase tracking-[0.08em] mb-2">Scope</label>
|
|
107
107
|
<div className="flex p-1 rounded-[12px] bg-bg border border-white/[0.06]">
|
|
108
108
|
{(['global', 'agent'] as const).map((s) => (
|
|
109
|
-
<button key={s} onClick={() => setSecretScope(s)} className={`flex-1 py-2.5 rounded-[10px] text-center cursor-pointer transition-all text-[13px] font-600 capitalize ${secretScope === s ? 'bg-accent-soft text-accent-bright' : 'bg-transparent text-text-3 hover:text-text-2'}`} style={{ fontFamily: 'inherit' }}>{s === 'global' ? 'All
|
|
109
|
+
<button key={s} onClick={() => setSecretScope(s)} className={`flex-1 py-2.5 rounded-[10px] text-center cursor-pointer transition-all text-[13px] font-600 capitalize ${secretScope === s ? 'bg-accent-soft text-accent-bright' : 'bg-transparent text-text-3 hover:text-text-2'}`} style={{ fontFamily: 'inherit' }}>{s === 'global' ? 'All Eligible Agents' : 'Specific Agents'}</button>
|
|
110
110
|
))}
|
|
111
111
|
</div>
|
|
112
112
|
</div>
|
|
113
113
|
|
|
114
|
-
{secretScope === 'agent' &&
|
|
114
|
+
{secretScope === 'agent' && selectableAgents.length > 0 && (
|
|
115
115
|
<div className="flex flex-wrap gap-2">
|
|
116
|
-
{
|
|
116
|
+
{selectableAgents.map((p) => (
|
|
117
117
|
<button key={p.id} onClick={() => setSecretAgentIds((prev) => prev.includes(p.id) ? prev.filter((x) => x !== p.id) : [...prev, p.id])} className={`px-3 py-2 rounded-[10px] text-[12px] font-600 cursor-pointer transition-all border ${secretAgentIds.includes(p.id) ? 'bg-accent-soft border-accent-bright/25 text-accent-bright' : 'bg-bg border-white/[0.06] text-text-3 hover:text-text-2'}`} style={{ fontFamily: 'inherit' }}>{p.name}</button>
|
|
118
118
|
))}
|
|
119
119
|
</div>
|
|
@@ -47,7 +47,7 @@ export function UserPreferencesSection({ appSettings, patchSettings, inputClass
|
|
|
47
47
|
<div className="mt-6">
|
|
48
48
|
<label className="text-[12px] font-600 text-text-2 block mb-1.5">Default Agent</label>
|
|
49
49
|
<p className="text-[11px] text-text-3/60 mb-2">
|
|
50
|
-
The agent that opens automatically when you start the app or
|
|
50
|
+
The agent that opens automatically when you start the app or use the default-agent shortcut.
|
|
51
51
|
</p>
|
|
52
52
|
<div className="flex flex-wrap gap-2">
|
|
53
53
|
<button
|