@swarmclawai/swarmclaw 0.7.1 → 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 +44 -5
- 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
|
@@ -8,13 +8,16 @@ export interface CapabilityPolicyBlock {
|
|
|
8
8
|
source: 'safety' | 'policy'
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export interface
|
|
11
|
+
export interface PluginPolicyDecision {
|
|
12
12
|
mode: CapabilityPolicyMode
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
requestedPlugins: string[]
|
|
14
|
+
enabledPlugins: string[]
|
|
15
|
+
blockedPlugins: CapabilityPolicyBlock[]
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** @deprecated Use PluginPolicyDecision */
|
|
19
|
+
export type SessionToolPolicyDecision = PluginPolicyDecision
|
|
20
|
+
|
|
18
21
|
type CapabilityCategory =
|
|
19
22
|
| 'filesystem'
|
|
20
23
|
| 'execution'
|
|
@@ -47,10 +50,11 @@ const TOOL_DESCRIPTORS: Record<string, ToolDescriptor> = {
|
|
|
47
50
|
web_search: { categories: ['network'], concreteTools: ['web_search'] },
|
|
48
51
|
web_fetch: { categories: ['network'], concreteTools: ['web_fetch'] },
|
|
49
52
|
browser: { categories: ['browser', 'network'], concreteTools: ['browser', 'openclaw_browser'] },
|
|
50
|
-
delegate: { categories: ['delegation', 'execution'], concreteTools: ['delegate', 'delegate_to_claude_code', 'delegate_to_codex_cli', 'delegate_to_opencode_cli'] },
|
|
53
|
+
delegate: { categories: ['delegation', 'execution'], concreteTools: ['delegate', 'delegate_to_claude_code', 'delegate_to_codex_cli', 'delegate_to_opencode_cli', 'delegate_to_gemini_cli'] },
|
|
51
54
|
claude_code: { categories: ['delegation', 'execution'], concreteTools: ['delegate_to_claude_code'] },
|
|
52
55
|
codex_cli: { categories: ['delegation', 'execution'], concreteTools: ['delegate_to_codex_cli'] },
|
|
53
56
|
opencode_cli: { categories: ['delegation', 'execution'], concreteTools: ['delegate_to_opencode_cli'] },
|
|
57
|
+
gemini_cli: { categories: ['delegation', 'execution'], concreteTools: ['delegate_to_gemini_cli'] },
|
|
54
58
|
memory: { categories: ['memory'], concreteTools: ['memory', 'memory_tool', 'context_status', 'context_summarize'] },
|
|
55
59
|
sandbox: { categories: ['execution', 'filesystem'], concreteTools: ['sandbox', 'sandbox_exec', 'sandbox_list_runtimes', 'openclaw_sandbox'] },
|
|
56
60
|
git: { categories: ['execution', 'filesystem'], concreteTools: ['git'] },
|
|
@@ -144,6 +148,7 @@ function safetyMatchesTool(safetyBlocked: Set<string>, toolName: string, descrip
|
|
|
144
148
|
if (toolName === 'claude_code' && safetyBlocked.has('delegate_to_claude_code')) return true
|
|
145
149
|
if (toolName === 'codex_cli' && safetyBlocked.has('delegate_to_codex_cli')) return true
|
|
146
150
|
if (toolName === 'opencode_cli' && safetyBlocked.has('delegate_to_opencode_cli')) return true
|
|
151
|
+
if (toolName === 'gemini_cli' && safetyBlocked.has('delegate_to_gemini_cli')) return true
|
|
147
152
|
return false
|
|
148
153
|
}
|
|
149
154
|
|
|
@@ -196,51 +201,51 @@ export function resolveSessionToolPolicy(
|
|
|
196
201
|
blockedCategories,
|
|
197
202
|
} = parsePolicyConfig(normalizedSettings)
|
|
198
203
|
|
|
199
|
-
const
|
|
200
|
-
? Array.from(new Set(sessionTools.map((
|
|
204
|
+
const requestedPlugins = Array.isArray(sessionTools)
|
|
205
|
+
? Array.from(new Set(sessionTools.map((id) => normalizeName(id)).filter(Boolean)))
|
|
201
206
|
: []
|
|
202
207
|
|
|
203
|
-
const
|
|
204
|
-
const
|
|
208
|
+
const enabledPlugins: string[] = []
|
|
209
|
+
const blockedPlugins: CapabilityPolicyBlock[] = []
|
|
205
210
|
|
|
206
|
-
for (const
|
|
207
|
-
const descriptor = TOOL_DESCRIPTORS[
|
|
211
|
+
for (const pluginName of requestedPlugins) {
|
|
212
|
+
const descriptor = TOOL_DESCRIPTORS[pluginName]
|
|
208
213
|
|
|
209
|
-
if (safetyMatchesTool(safetyBlocked,
|
|
210
|
-
|
|
214
|
+
if (safetyMatchesTool(safetyBlocked, pluginName, descriptor)) {
|
|
215
|
+
blockedPlugins.push({ tool: pluginName, reason: 'blocked by safety policy', source: 'safety' })
|
|
211
216
|
continue
|
|
212
217
|
}
|
|
213
218
|
|
|
214
|
-
if (policyAllowedNames.has(
|
|
215
|
-
|
|
219
|
+
if (policyAllowedNames.has(pluginName)) {
|
|
220
|
+
enabledPlugins.push(pluginName)
|
|
216
221
|
continue
|
|
217
222
|
}
|
|
218
223
|
|
|
219
|
-
if (policyMatchesTool(policyBlockedNames,
|
|
220
|
-
|
|
224
|
+
if (policyMatchesTool(policyBlockedNames, pluginName, descriptor)) {
|
|
225
|
+
blockedPlugins.push({ tool: pluginName, reason: 'blocked by explicit policy rule', source: 'policy' })
|
|
221
226
|
continue
|
|
222
227
|
}
|
|
223
228
|
|
|
224
229
|
const categoryReason = categoryBlockReason(blockedCategories, descriptor)
|
|
225
230
|
if (categoryReason) {
|
|
226
|
-
|
|
231
|
+
blockedPlugins.push({ tool: pluginName, reason: categoryReason, source: 'policy' })
|
|
227
232
|
continue
|
|
228
233
|
}
|
|
229
234
|
|
|
230
|
-
const modeReason = modeBlocksTool(mode,
|
|
235
|
+
const modeReason = modeBlocksTool(mode, pluginName, descriptor)
|
|
231
236
|
if (modeReason) {
|
|
232
|
-
|
|
237
|
+
blockedPlugins.push({ tool: pluginName, reason: modeReason, source: 'policy' })
|
|
233
238
|
continue
|
|
234
239
|
}
|
|
235
240
|
|
|
236
|
-
|
|
241
|
+
enabledPlugins.push(pluginName)
|
|
237
242
|
}
|
|
238
243
|
|
|
239
244
|
return {
|
|
240
245
|
mode,
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
requestedPlugins,
|
|
247
|
+
enabledPlugins,
|
|
248
|
+
blockedPlugins,
|
|
244
249
|
}
|
|
245
250
|
}
|
|
246
251
|
|
|
@@ -270,11 +275,11 @@ export function resolveConcreteToolPolicyBlock(
|
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
if (mappedTool) {
|
|
273
|
-
const blockedRoot = decision.
|
|
278
|
+
const blockedRoot = decision.blockedPlugins.find((entry) => entry.tool === mappedTool)
|
|
274
279
|
if (blockedRoot) return blockedRoot.reason
|
|
275
280
|
|
|
276
|
-
const enabledRoot = decision.
|
|
277
|
-
if (!enabledRoot) return `
|
|
281
|
+
const enabledRoot = decision.enabledPlugins.includes(mappedTool)
|
|
282
|
+
if (!enabledRoot) return `plugin family "${mappedTool}" is not enabled for this chat`
|
|
278
283
|
}
|
|
279
284
|
|
|
280
285
|
return null
|
|
@@ -25,6 +25,10 @@ export const AVAILABLE_TOOLS: ToolDefinition[] = [
|
|
|
25
25
|
{ id: 'monitor', label: 'Monitor', description: 'System observability: check resource usage, watch logs, and ping endpoints' },
|
|
26
26
|
{ id: 'plugin_creator', label: 'Plugin Creator', description: 'Design, write, and test custom SwarmClaw plugins dynamically' },
|
|
27
27
|
{ id: 'sample_ui', label: 'Sample UI', description: 'Demonstration of dynamic UI injection into Sidebar and Chat Header' },
|
|
28
|
+
{ id: 'image_gen', label: 'Image Generation', description: 'Generate images from text prompts using OpenAI, Stability AI, Replicate, fal.ai, and more' },
|
|
29
|
+
{ id: 'email', label: 'Email', description: 'Send emails via SMTP with plain text and HTML support' },
|
|
30
|
+
{ id: 'calendar', label: 'Calendar', description: 'Manage Google Calendar or Outlook events — list, create, update, delete' },
|
|
31
|
+
{ id: 'replicate', label: 'Replicate', description: 'Run any AI model on Replicate — image generation, LLMs, audio, video, and more' },
|
|
28
32
|
]
|
|
29
33
|
|
|
30
34
|
/**
|
|
@@ -10,7 +10,9 @@ export const AgentCreateSchema = z.object({
|
|
|
10
10
|
apiEndpoint: z.string().nullable().optional().default(null),
|
|
11
11
|
isOrchestrator: z.boolean().optional().default(false),
|
|
12
12
|
subAgentIds: z.array(z.string()).optional().default([]),
|
|
13
|
-
|
|
13
|
+
plugins: z.array(z.string()).optional().default([]),
|
|
14
|
+
/** @deprecated Use plugins */
|
|
15
|
+
tools: z.array(z.string()).optional(),
|
|
14
16
|
capabilities: z.array(z.string()).optional().default([]),
|
|
15
17
|
thinkingLevel: z.string().optional(),
|
|
16
18
|
soul: z.string().optional(),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { create } from 'zustand'
|
|
4
4
|
import type { Sessions, Session, NetworkInfo, Directory, ProviderInfo, Credentials, Agent, Schedule, AppView, BoardTask, AppSettings, OrchestratorSecret, ProviderConfig, Skill, Connector, Webhook, McpServerConfig, PluginMeta, Project, FleetFilter, ActivityEntry, AppNotification, ApprovalRequest } from '../types'
|
|
5
|
-
import {
|
|
5
|
+
import { fetchChats, fetchDirs, fetchProviders, fetchCredentials } from '../lib/chats'
|
|
6
6
|
import { fetchAgents } from '../lib/agents'
|
|
7
7
|
import { fetchSchedules } from '../lib/schedules'
|
|
8
8
|
import { fetchTasks } from '../lib/tasks'
|
|
@@ -235,7 +235,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|
|
235
235
|
currentSessionId: null,
|
|
236
236
|
loadSessions: async () => {
|
|
237
237
|
try {
|
|
238
|
-
const sessions = await
|
|
238
|
+
const sessions = await fetchChats()
|
|
239
239
|
set({ sessions })
|
|
240
240
|
} catch {
|
|
241
241
|
// ignore
|
|
@@ -249,7 +249,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|
|
249
249
|
},
|
|
250
250
|
clearSessions: async (ids) => {
|
|
251
251
|
if (!ids.length) return
|
|
252
|
-
await api('DELETE', '/
|
|
252
|
+
await api('DELETE', '/chats', { ids })
|
|
253
253
|
const sessions = { ...get().sessions }
|
|
254
254
|
for (const id of ids) delete sessions[id]
|
|
255
255
|
set({ sessions, currentSessionId: ids.includes(get().currentSessionId!) ? null : get().currentSessionId })
|
|
@@ -260,7 +260,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|
|
260
260
|
sessions[id] = { ...sessions[id], pinned: !sessions[id].pinned }
|
|
261
261
|
set({ sessions })
|
|
262
262
|
// Persist to server
|
|
263
|
-
void api('PUT', `/
|
|
263
|
+
void api('PUT', `/chats/${id}`, { pinned: sessions[id].pinned })
|
|
264
264
|
}
|
|
265
265
|
},
|
|
266
266
|
updateSessionInStore: (session) => {
|
|
@@ -268,7 +268,7 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|
|
268
268
|
},
|
|
269
269
|
forkSession: async (sessionId, messageIndex) => {
|
|
270
270
|
try {
|
|
271
|
-
const forked = await api<Session>('POST', `/
|
|
271
|
+
const forked = await api<Session>('POST', `/chats/${sessionId}/fork`, { messageIndex })
|
|
272
272
|
if (!forked?.id) return null
|
|
273
273
|
await get().loadSessions()
|
|
274
274
|
set({ currentSessionId: forked.id })
|
|
@@ -407,7 +407,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
407
407
|
if (!sessionId) return
|
|
408
408
|
try {
|
|
409
409
|
const key = getStoredAccessKey()
|
|
410
|
-
const res = await fetch(`/api/
|
|
410
|
+
const res = await fetch(`/api/chats/${sessionId}/edit-resend`, {
|
|
411
411
|
method: 'POST',
|
|
412
412
|
headers: {
|
|
413
413
|
'Content-Type': 'application/json',
|
|
@@ -417,7 +417,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
417
417
|
})
|
|
418
418
|
if (!res.ok) return
|
|
419
419
|
// Reload messages from server (truncated)
|
|
420
|
-
const msgsRes = await fetch(`/api/
|
|
420
|
+
const msgsRes = await fetch(`/api/chats/${sessionId}/messages`, {
|
|
421
421
|
headers: key ? { 'X-Access-Key': key } : undefined,
|
|
422
422
|
})
|
|
423
423
|
if (msgsRes.ok) {
|
|
@@ -437,7 +437,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
437
437
|
if (!sessionId) return
|
|
438
438
|
try {
|
|
439
439
|
const key = getStoredAccessKey()
|
|
440
|
-
const res = await fetch(`/api/
|
|
440
|
+
const res = await fetch(`/api/chats/${sessionId}/retry`, {
|
|
441
441
|
method: 'POST',
|
|
442
442
|
headers: key ? { 'X-Access-Key': key } : undefined,
|
|
443
443
|
})
|
|
@@ -445,7 +445,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
445
445
|
const { message, imagePath } = await res.json()
|
|
446
446
|
if (!message) return
|
|
447
447
|
// Reload messages from server (without the popped ones)
|
|
448
|
-
const msgsRes = await fetch(`/api/
|
|
448
|
+
const msgsRes = await fetch(`/api/chats/${sessionId}/messages`, {
|
|
449
449
|
headers: key ? { 'X-Access-Key': key } : undefined,
|
|
450
450
|
})
|
|
451
451
|
if (msgsRes.ok) {
|
|
@@ -546,7 +546,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
546
546
|
set((s) => ({ messages: [...s.messages, marker] }))
|
|
547
547
|
try {
|
|
548
548
|
const key = getStoredAccessKey()
|
|
549
|
-
await fetch(`/api/
|
|
549
|
+
await fetch(`/api/chats/${sessionId}/messages`, {
|
|
550
550
|
method: 'POST',
|
|
551
551
|
headers: { 'Content-Type': 'application/json', ...(key ? { 'X-Access-Key': key } : {}) },
|
|
552
552
|
body: JSON.stringify({ kind: 'context-clear' }),
|
|
@@ -569,7 +569,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
569
569
|
const key = getStoredAccessKey()
|
|
570
570
|
// Find the earliest message's original index (startIndex tracked on initial load)
|
|
571
571
|
const currentStartIndex = totalMessages - messages.length
|
|
572
|
-
const res = await fetch(`/api/
|
|
572
|
+
const res = await fetch(`/api/chats/${sessionId}/messages?limit=100&before=${currentStartIndex}`, {
|
|
573
573
|
headers: key ? { 'X-Access-Key': key } : undefined,
|
|
574
574
|
})
|
|
575
575
|
if (res.ok) {
|
|
@@ -593,7 +593,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|
|
593
593
|
if (sessionId) {
|
|
594
594
|
try {
|
|
595
595
|
const key = getStoredAccessKey()
|
|
596
|
-
await fetch(`/api/
|
|
596
|
+
await fetch(`/api/chats/${sessionId}/stop`, {
|
|
597
597
|
method: 'POST',
|
|
598
598
|
headers: key ? { 'X-Access-Key': key } : undefined,
|
|
599
599
|
})
|
package/src/types/index.ts
CHANGED
|
@@ -63,15 +63,17 @@ export interface Session {
|
|
|
63
63
|
claudeCode?: string | null
|
|
64
64
|
codex?: string | null
|
|
65
65
|
opencode?: string | null
|
|
66
|
+
gemini?: string | null
|
|
66
67
|
}
|
|
67
68
|
messages: Message[]
|
|
68
69
|
createdAt: number
|
|
69
70
|
lastActiveAt: number
|
|
70
71
|
active?: boolean
|
|
71
|
-
mainSession?: boolean
|
|
72
72
|
sessionType?: SessionType
|
|
73
73
|
agentId?: string | null
|
|
74
74
|
parentSessionId?: string | null
|
|
75
|
+
plugins?: string[]
|
|
76
|
+
/** @deprecated Use `plugins` instead. Kept for backward compat with stored data. */
|
|
75
77
|
tools?: string[]
|
|
76
78
|
heartbeatEnabled?: boolean | null
|
|
77
79
|
heartbeatIntervalSec?: number | null
|
|
@@ -167,6 +169,18 @@ export interface ApprovalRequest {
|
|
|
167
169
|
|
|
168
170
|
export type Approvals = Record<string, ApprovalRequest>
|
|
169
171
|
|
|
172
|
+
export interface PluginInvocationRecord {
|
|
173
|
+
pluginId: string
|
|
174
|
+
toolName: string
|
|
175
|
+
inputTokens: number
|
|
176
|
+
outputTokens: number
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface PluginDefinitionCost {
|
|
180
|
+
pluginId: string
|
|
181
|
+
estimatedTokens: number
|
|
182
|
+
}
|
|
183
|
+
|
|
170
184
|
export interface UsageRecord {
|
|
171
185
|
sessionId: string
|
|
172
186
|
messageIndex: number
|
|
@@ -178,6 +192,8 @@ export interface UsageRecord {
|
|
|
178
192
|
estimatedCost: number
|
|
179
193
|
timestamp: number
|
|
180
194
|
durationMs?: number
|
|
195
|
+
pluginDefinitionCosts?: PluginDefinitionCost[]
|
|
196
|
+
pluginInvocations?: PluginInvocationRecord[]
|
|
181
197
|
}
|
|
182
198
|
|
|
183
199
|
// --- Plugin System ---
|
|
@@ -186,9 +202,12 @@ export interface PluginHooks {
|
|
|
186
202
|
beforeAgentStart?: (ctx: { session: Session; message: string }) => Promise<void> | void
|
|
187
203
|
afterAgentComplete?: (ctx: { session: Session; response: string }) => Promise<void> | void
|
|
188
204
|
beforeToolExec?: (ctx: { toolName: string; input: Record<string, unknown> | null }) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void
|
|
189
|
-
afterToolExec?: (ctx: { toolName: string; input: Record<string, unknown> | null; output: string }) => Promise<void> | void
|
|
205
|
+
afterToolExec?: (ctx: { session: Session; toolName: string; input: Record<string, unknown> | null; output: string }) => Promise<void> | void
|
|
190
206
|
onMessage?: (ctx: { session: Session; message: Message }) => Promise<void> | void
|
|
191
207
|
|
|
208
|
+
// Post-turn hook — fires after a full chat exchange (user message → agent response)
|
|
209
|
+
afterChatTurn?: (ctx: { session: Session; message: string; response: string; source: string; internal: boolean }) => Promise<void> | void
|
|
210
|
+
|
|
192
211
|
// Orchestration & Swarm Hooks
|
|
193
212
|
onTaskComplete?: (ctx: { taskId: string; result: unknown }) => Promise<void> | void
|
|
194
213
|
onAgentDelegation?: (ctx: { sourceAgentId: string; targetAgentId: string; task: string }) => Promise<void> | void
|
|
@@ -196,6 +215,15 @@ export interface PluginHooks {
|
|
|
196
215
|
// Chat Middleware (Transform messages)
|
|
197
216
|
transformInboundMessage?: (ctx: { session: Session; text: string }) => Promise<string> | string
|
|
198
217
|
transformOutboundMessage?: (ctx: { session: Session; text: string }) => Promise<string> | string
|
|
218
|
+
|
|
219
|
+
// Context injection — return a markdown string to inject into the agent's state modifier, or null/undefined to skip
|
|
220
|
+
getAgentContext?: (ctx: { session: Session; enabledPlugins: string[]; message: string; history: Message[] }) => Promise<string | null | undefined> | string | null | undefined
|
|
221
|
+
|
|
222
|
+
// Self-description — returns a capability line for the system prompt (e.g., "I can remember things across conversations")
|
|
223
|
+
getCapabilityDescription?: () => string | null | undefined
|
|
224
|
+
|
|
225
|
+
// Operating guidance — returns operational hints for the agent when this plugin is active
|
|
226
|
+
getOperatingGuidance?: () => string | string[] | null | undefined
|
|
199
227
|
}
|
|
200
228
|
|
|
201
229
|
export interface PluginToolDef {
|
|
@@ -205,6 +233,17 @@ export interface PluginToolDef {
|
|
|
205
233
|
execute: (args: Record<string, unknown>, ctx: { session: Session; message: string }) => Promise<string | object> | string | object
|
|
206
234
|
}
|
|
207
235
|
|
|
236
|
+
export interface PluginSettingsField {
|
|
237
|
+
key: string
|
|
238
|
+
label: string
|
|
239
|
+
type: 'text' | 'number' | 'boolean' | 'select' | 'secret'
|
|
240
|
+
placeholder?: string
|
|
241
|
+
help?: string
|
|
242
|
+
options?: Array<{ value: string; label: string }>
|
|
243
|
+
defaultValue?: string | number | boolean
|
|
244
|
+
required?: boolean
|
|
245
|
+
}
|
|
246
|
+
|
|
208
247
|
export interface PluginUIExtension {
|
|
209
248
|
sidebarItems?: Array<{
|
|
210
249
|
id: string
|
|
@@ -226,6 +265,22 @@ export interface PluginUIExtension {
|
|
|
226
265
|
action: 'message' | 'link' | 'tool'
|
|
227
266
|
value: string
|
|
228
267
|
}>
|
|
268
|
+
/** Settings fields declared by the plugin, rendered in the plugin settings panel */
|
|
269
|
+
settingsFields?: PluginSettingsField[]
|
|
270
|
+
/** Chat panels the plugin provides (e.g., browser view, terminal) */
|
|
271
|
+
chatPanels?: Array<{
|
|
272
|
+
id: string
|
|
273
|
+
label: string
|
|
274
|
+
icon?: string
|
|
275
|
+
/** WS topic to subscribe to for updates (e.g., 'browser:{sessionId}') */
|
|
276
|
+
wsTopic?: string
|
|
277
|
+
}>
|
|
278
|
+
/** Badges to show on agent cards when this plugin is enabled */
|
|
279
|
+
agentBadges?: Array<{
|
|
280
|
+
id: string
|
|
281
|
+
label: string
|
|
282
|
+
icon?: string
|
|
283
|
+
}>
|
|
229
284
|
}
|
|
230
285
|
|
|
231
286
|
export interface PluginProviderExtension {
|
|
@@ -252,6 +307,7 @@ export interface Plugin {
|
|
|
252
307
|
name: string
|
|
253
308
|
version?: string
|
|
254
309
|
description?: string
|
|
310
|
+
enabledByDefault?: boolean
|
|
255
311
|
hooks?: PluginHooks
|
|
256
312
|
tools?: PluginToolDef[]
|
|
257
313
|
ui?: PluginUIExtension
|
|
@@ -279,6 +335,7 @@ export interface PluginMeta {
|
|
|
279
335
|
providerCount?: number
|
|
280
336
|
connectorCount?: number
|
|
281
337
|
createdByAgentId?: string | null
|
|
338
|
+
settingsFields?: PluginSettingsField[]
|
|
282
339
|
}
|
|
283
340
|
export interface MarketplacePlugin {
|
|
284
341
|
id: string
|
|
@@ -350,7 +407,9 @@ export interface Agent {
|
|
|
350
407
|
apiEndpoint?: string | null
|
|
351
408
|
isOrchestrator?: boolean
|
|
352
409
|
subAgentIds?: string[]
|
|
353
|
-
|
|
410
|
+
plugins?: string[] // e.g. ['browser', 'memory'] — enabled plugin IDs
|
|
411
|
+
/** @deprecated Use `plugins` instead. Kept for backward compat with stored data. */
|
|
412
|
+
tools?: string[]
|
|
354
413
|
skills?: string[] // e.g. ['frontend-design'] — Claude Code skills to use
|
|
355
414
|
skillIds?: string[] // IDs of uploaded skills from the Skills manager
|
|
356
415
|
mcpServerIds?: string[] // IDs of configured MCP servers to inject tools from
|
|
@@ -784,6 +843,8 @@ export interface AppSettings {
|
|
|
784
843
|
taskQualityGateRequireReport?: boolean
|
|
785
844
|
// Integrity monitor
|
|
786
845
|
integrityMonitorEnabled?: boolean
|
|
846
|
+
// Per-plugin settings (keyed by pluginId)
|
|
847
|
+
pluginSettings?: Record<string, Record<string, unknown>>
|
|
787
848
|
}
|
|
788
849
|
|
|
789
850
|
// --- Orchestrator Secrets ---
|
|
@@ -977,6 +1038,7 @@ export interface BoardTask {
|
|
|
977
1038
|
claudeResumeId?: string | null
|
|
978
1039
|
codexResumeId?: string | null
|
|
979
1040
|
opencodeResumeId?: string | null
|
|
1041
|
+
geminiResumeId?: string | null
|
|
980
1042
|
checkpoint?: {
|
|
981
1043
|
lastRunId?: string | null
|
|
982
1044
|
lastSessionId?: string | null
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|