@swarmclawai/swarmclaw 1.2.6 → 1.2.9
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 +54 -23
- package/next.config.ts +1 -0
- package/package.json +4 -3
- package/scripts/easy-setup.mjs +1 -1
- package/scripts/postinstall.mjs +1 -1
- package/skills/swarmclaw.md +115 -0
- package/skills/tools/browser.md +131 -0
- package/skills/tools/execute.md +98 -0
- package/skills/tools/files.md +98 -0
- package/skills/tools/memory.md +104 -0
- package/skills/tools/platform.md +144 -0
- package/skills/tools/skills.md +83 -0
- package/src/app/agents/[id]/page.tsx +1 -18
- package/src/app/api/agents/thread-route.test.ts +0 -1
- package/src/app/api/approvals/route.test.ts +6 -22
- package/src/app/api/chats/[id]/messages/route.ts +23 -19
- package/src/app/api/chats/messages-route.test.ts +105 -51
- package/src/app/api/connectors/route.ts +2 -2
- package/src/app/api/mcp-servers/[id]/test/route.ts +3 -2
- package/src/app/api/openclaw/deploy/route.ts +2 -0
- package/src/app/api/portability/export/route.ts +8 -0
- package/src/app/api/portability/import/route.test.ts +80 -0
- package/src/app/api/portability/import/route.ts +28 -0
- package/src/app/api/settings/route.ts +0 -2
- package/src/app/api/setup/doctor/route.ts +4 -4
- package/src/app/api/wallets/[id]/route.ts +15 -157
- package/src/app/api/wallets/generate/route.ts +22 -0
- package/src/app/api/wallets/route.test.ts +147 -0
- package/src/app/api/wallets/route.ts +13 -95
- package/src/app/autonomy/page.tsx +2 -57
- package/src/app/protocols/page.tsx +2 -21
- package/src/app/settings/page.tsx +0 -9
- package/src/app/wallets/page.tsx +105 -5
- package/src/cli/index.js +21 -33
- package/src/cli/spec.js +19 -30
- package/src/components/agents/agent-chat-list.tsx +23 -1
- package/src/components/agents/agent-sheet.tsx +2 -40
- package/src/components/agents/inspector-panel.tsx +165 -131
- package/src/components/chat/chat-area.tsx +38 -9
- package/src/components/chat/chat-card.tsx +0 -31
- package/src/components/chat/message-bubble.tsx +1 -108
- package/src/components/chat/message-list.tsx +33 -19
- package/src/components/connectors/connector-sheet.tsx +25 -1
- package/src/components/gateways/gateway-sheet.tsx +5 -2
- package/src/components/layout/sidebar-rail.tsx +6 -10
- package/src/components/projects/project-detail.tsx +3 -35
- package/src/components/projects/tabs/overview-tab.tsx +3 -59
- package/src/components/projects/tabs/work-tab.tsx +7 -77
- package/src/components/protocols/structured-session-launcher.tsx +1 -22
- package/src/components/shared/connector-platform-icon.tsx +1 -0
- package/src/components/tasks/task-card.tsx +4 -34
- package/src/components/tasks/task-sheet.tsx +6 -36
- package/src/components/wallets/wallet-list.tsx +150 -0
- package/src/lib/agent-execute-defaults.test.ts +24 -0
- package/src/lib/agent-execute-defaults.ts +62 -0
- package/src/lib/app/navigation.test.ts +0 -13
- package/src/lib/app/navigation.ts +2 -7
- package/src/lib/app/view-constants.ts +14 -19
- package/src/lib/chat/queued-message-queue.test.ts +134 -1
- package/src/lib/chat/queued-message-queue.ts +77 -2
- package/src/lib/server/agents/agent-service.ts +5 -0
- package/src/lib/server/agents/agent-thread-session.ts +0 -1
- package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
- package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
- package/src/lib/server/agents/delegation-jobs.ts +0 -25
- package/src/lib/server/agents/main-agent-loop.ts +1 -49
- package/src/lib/server/agents/subagent-runtime.ts +0 -1
- package/src/lib/server/approval-match.ts +0 -85
- package/src/lib/server/approvals.test.ts +6 -6
- package/src/lib/server/approvals.ts +0 -6
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
- package/src/lib/server/builtin-extensions.ts +1 -2
- package/src/lib/server/capability-router.test.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-advanced.test.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +15 -14
- package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-utils.ts +2 -4
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +81 -64
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -0
- package/src/lib/server/chat-execution/continuation-evaluator.ts +8 -0
- package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
- package/src/lib/server/chat-execution/memory-mutation-tools.ts +1 -1
- package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
- package/src/lib/server/chat-execution/message-classifier.ts +11 -16
- package/src/lib/server/chat-execution/prompt-builder.test.ts +27 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +14 -31
- package/src/lib/server/chat-execution/prompt-mode.test.ts +24 -0
- package/src/lib/server/chat-execution/prompt-mode.ts +5 -1
- package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
- package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
- package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
- package/src/lib/server/chat-execution/stream-agent-chat.test.ts +13 -126
- package/src/lib/server/chat-execution/stream-agent-chat.ts +46 -21
- package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
- package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
- package/src/lib/server/chatrooms/chatroom-routing.test.ts +4 -0
- package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
- package/src/lib/server/chats/chat-session-service.ts +3 -5
- package/src/lib/server/connectors/connector-inbound.ts +0 -1
- package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
- package/src/lib/server/connectors/connector-service.ts +39 -9
- package/src/lib/server/connectors/discord.ts +2 -2
- package/src/lib/server/connectors/matrix.ts +3 -2
- package/src/lib/server/connectors/signal.ts +5 -4
- package/src/lib/server/connectors/slack.ts +10 -9
- package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
- package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
- package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
- package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
- package/src/lib/server/connectors/swarmdock-tasks.ts +119 -0
- package/src/lib/server/connectors/swarmdock.ts +255 -0
- package/src/lib/server/connectors/teams.ts +3 -2
- package/src/lib/server/connectors/telegram.ts +4 -4
- package/src/lib/server/connectors/whatsapp.ts +2 -2
- package/src/lib/server/daemon/controller.ts +7 -0
- package/src/lib/server/execution-brief.test.ts +2 -25
- package/src/lib/server/execution-brief.ts +12 -35
- package/src/lib/server/execution-engine/task-attempt.ts +0 -1
- package/src/lib/server/gateways/gateway-profile-service.ts +19 -1
- package/src/lib/server/messages/message-repository.test.ts +70 -0
- package/src/lib/server/messages/message-repository.ts +11 -6
- package/src/lib/server/openclaw/deploy.ts +32 -2
- package/src/lib/server/persistence/storage-context.ts +0 -5
- package/src/lib/server/plugins-advanced.test.ts +1 -2
- package/src/lib/server/portability/export.ts +109 -0
- package/src/lib/server/portability/import.ts +159 -0
- package/src/lib/server/protocols/protocol-normalization.ts +0 -4
- package/src/lib/server/protocols/protocol-queries.ts +0 -6
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
- package/src/lib/server/protocols/protocol-service.ts +0 -1
- package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
- package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
- package/src/lib/server/protocols/protocol-swarm.ts +0 -2
- package/src/lib/server/protocols/protocol-types.ts +0 -2
- package/src/lib/server/provider-health.ts +1 -10
- package/src/lib/server/runtime/daemon-state/core.ts +0 -9
- package/src/lib/server/runtime/daemon-state.test.ts +0 -35
- package/src/lib/server/runtime/heartbeat-service.ts +3 -23
- package/src/lib/server/runtime/process-manager.ts +13 -9
- package/src/lib/server/runtime/queue/core.ts +11 -33
- package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
- package/src/lib/server/runtime/scheduler.ts +0 -13
- package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
- package/src/lib/server/runtime/session-run-manager/queries.ts +15 -1
- package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
- package/src/lib/server/runtime/session-run-manager.test.ts +58 -28
- package/src/lib/server/sandbox/session-runtime.test.ts +18 -1
- package/src/lib/server/sandbox/session-runtime.ts +40 -28
- package/src/lib/server/session-tools/autonomy-tools.test.ts +7 -9
- package/src/lib/server/session-tools/context.ts +1 -1
- package/src/lib/server/session-tools/credential-env.ts +109 -0
- package/src/lib/server/session-tools/crud.ts +3 -17
- package/src/lib/server/session-tools/delegate.ts +0 -4
- package/src/lib/server/session-tools/edit_file.ts +3 -2
- package/src/lib/server/session-tools/execute.test.ts +58 -0
- package/src/lib/server/session-tools/execute.ts +334 -0
- package/src/lib/server/session-tools/files-tool.ts +635 -0
- package/src/lib/server/session-tools/index.ts +14 -8
- package/src/lib/server/session-tools/memory-tool.ts +242 -0
- package/src/lib/server/session-tools/memory.ts +1 -1
- package/src/lib/server/session-tools/openclaw-nodes.ts +3 -2
- package/src/lib/server/session-tools/openclaw-workspace.ts +3 -2
- package/src/lib/server/session-tools/platform-tool.ts +617 -0
- package/src/lib/server/session-tools/session-info.ts +3 -2
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +3 -4
- package/src/lib/server/session-tools/shell.ts +7 -122
- package/src/lib/server/session-tools/skills-tool.ts +396 -0
- package/src/lib/server/session-tools/team-context.ts +0 -3
- package/src/lib/server/session-tools/web.ts +2 -2
- package/src/lib/server/storage-normalization.ts +10 -0
- package/src/lib/server/storage.ts +18 -45
- package/src/lib/server/tasks/task-checkout.ts +59 -0
- package/src/lib/server/tasks/task-lifecycle.ts +2 -0
- package/src/lib/server/tasks/task-route-service.ts +4 -26
- package/src/lib/server/tasks/task-service.ts +0 -7
- package/src/lib/server/tool-aliases.ts +2 -2
- package/src/lib/server/tool-capability-policy-advanced.test.ts +13 -6
- package/src/lib/server/tool-capability-policy.test.ts +2 -1
- package/src/lib/server/tool-capability-policy.ts +60 -35
- package/src/lib/server/tool-planning.ts +11 -12
- package/src/lib/server/universal-tool-access.ts +0 -1
- package/src/lib/server/wallets/wallet-crypto.ts +33 -0
- package/src/lib/server/wallets/wallet-repository.ts +24 -0
- package/src/lib/server/wallets/wallet-service.ts +119 -0
- package/src/lib/server/working-state/extraction.ts +8 -42
- package/src/lib/server/working-state/normalization.ts +10 -103
- package/src/lib/server/working-state/service.ts +12 -21
- package/src/lib/setup-defaults.ts +5 -0
- package/src/lib/strip-internal-metadata.test.ts +1 -1
- package/src/lib/strip-internal-metadata.ts +1 -1
- package/src/lib/tool-definitions.ts +1 -1
- package/src/lib/validation/schemas.test.ts +16 -0
- package/src/lib/validation/schemas.ts +49 -2
- package/src/stores/slices/data-slice.ts +5 -1
- package/src/stores/slices/ui-slice.ts +0 -4
- package/src/stores/use-chat-store.test.ts +231 -0
- package/src/stores/use-chat-store.ts +62 -13
- package/src/types/agent.ts +264 -0
- package/src/types/app-settings.ts +173 -0
- package/src/types/approval.ts +25 -0
- package/src/types/connector.ts +188 -0
- package/src/types/extension.ts +386 -0
- package/src/types/index.ts +16 -3555
- package/src/types/message.ts +56 -0
- package/src/types/misc.ts +737 -0
- package/src/types/protocol.ts +420 -0
- package/src/types/provider.ts +52 -0
- package/src/types/run.ts +180 -0
- package/src/types/schedule.ts +59 -0
- package/src/types/session.ts +215 -0
- package/src/types/skill.ts +157 -0
- package/src/types/swarmdock.ts +29 -0
- package/src/types/task.ts +144 -0
- package/src/types/working-state.ts +204 -0
- package/src/views/settings/section-heartbeat.tsx +2 -2
- package/src/views/settings/section-runtime-loop.tsx +0 -14
- package/src/app/api/canvas/[sessionId]/route.ts +0 -35
- package/src/app/api/missions/[id]/actions/route.ts +0 -31
- package/src/app/api/missions/[id]/events/route.ts +0 -14
- package/src/app/api/missions/[id]/route.ts +0 -10
- package/src/app/api/missions/route.test.ts +0 -244
- package/src/app/api/missions/route.ts +0 -57
- package/src/app/api/wallets/[id]/approve/route.ts +0 -79
- package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
- package/src/app/api/wallets/[id]/send/route.ts +0 -113
- package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
- package/src/app/missions/[id]/page.tsx +0 -3
- package/src/app/missions/page.tsx +0 -685
- package/src/components/canvas/canvas-panel.tsx +0 -267
- package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
- package/src/components/wallets/wallet-panel.tsx +0 -1010
- package/src/components/wallets/wallet-section.tsx +0 -260
- package/src/features/missions/queries.ts +0 -23
- package/src/lib/canvas-content.test.ts +0 -360
- package/src/lib/canvas-content.ts +0 -198
- package/src/lib/server/canvas-content.test.ts +0 -32
- package/src/lib/server/canvas-content.ts +0 -6
- package/src/lib/server/ethereum.ts +0 -591
- package/src/lib/server/evm-swap.ts +0 -476
- package/src/lib/server/missions/mission-intent.test.ts +0 -63
- package/src/lib/server/missions/mission-intent.ts +0 -569
- package/src/lib/server/missions/mission-repository.ts +0 -74
- package/src/lib/server/missions/mission-service/actions.ts +0 -6
- package/src/lib/server/missions/mission-service/bindings.ts +0 -9
- package/src/lib/server/missions/mission-service/context.ts +0 -4
- package/src/lib/server/missions/mission-service/core.ts +0 -2271
- package/src/lib/server/missions/mission-service/queries.ts +0 -12
- package/src/lib/server/missions/mission-service/recovery.ts +0 -5
- package/src/lib/server/missions/mission-service/ticks.ts +0 -9
- package/src/lib/server/missions/mission-service.test.ts +0 -888
- package/src/lib/server/missions/mission-service.ts +0 -6
- package/src/lib/server/session-tools/canvas.ts +0 -105
- package/src/lib/server/session-tools/sandbox.ts +0 -281
- package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
- package/src/lib/server/session-tools/wallet.ts +0 -1287
- package/src/lib/server/solana.ts +0 -327
- package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
- package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
- package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
- package/src/lib/server/wallet/wallet-service.test.ts +0 -81
- package/src/lib/server/wallet/wallet-service.ts +0 -225
- package/src/lib/wallet/wallet-transactions.test.ts +0 -75
- package/src/lib/wallet/wallet-transactions.ts +0 -43
- package/src/lib/wallet/wallet.test.ts +0 -333
- package/src/lib/wallet/wallet.ts +0 -183
- package/src/views/settings/section-wallets.tsx +0 -35
|
@@ -78,7 +78,6 @@ import {
|
|
|
78
78
|
buildToolAvailabilityLines,
|
|
79
79
|
buildToolDisciplineLines,
|
|
80
80
|
buildToolSection,
|
|
81
|
-
buildExternalWalletExecutionBlock,
|
|
82
81
|
buildForcedExternalServiceSummary,
|
|
83
82
|
shouldForceAttachmentFollowthrough,
|
|
84
83
|
joinPromptSegments,
|
|
@@ -101,7 +100,6 @@ import { finalizeStreamResult } from '@/lib/server/chat-execution/post-stream-fi
|
|
|
101
100
|
import {
|
|
102
101
|
classifyMessage,
|
|
103
102
|
isDeliverableTask as classifiedIsDeliverableTask,
|
|
104
|
-
hasTransactionalWalletIntent as classifiedHasTransactionalWalletIntent,
|
|
105
103
|
isResearchSynthesis as classifiedIsResearchSynthesis,
|
|
106
104
|
type MessageClassification,
|
|
107
105
|
} from '@/lib/server/chat-execution/message-classifier'
|
|
@@ -125,7 +123,6 @@ export {
|
|
|
125
123
|
buildToolAvailabilityLines,
|
|
126
124
|
buildToolDisciplineLines,
|
|
127
125
|
buildToolSection,
|
|
128
|
-
buildExternalWalletExecutionBlock,
|
|
129
126
|
shouldForceAttachmentFollowthrough,
|
|
130
127
|
buildForcedExternalServiceSummary,
|
|
131
128
|
}
|
|
@@ -142,7 +139,6 @@ export {
|
|
|
142
139
|
} from '@/lib/server/chat-execution/stream-continuation'
|
|
143
140
|
|
|
144
141
|
export {
|
|
145
|
-
isWalletSimulationResult,
|
|
146
142
|
resolveSuccessfulTerminalToolBoundary,
|
|
147
143
|
shouldForceExternalServiceSummary,
|
|
148
144
|
} from '@/lib/server/chat-execution/chat-streaming-utils'
|
|
@@ -190,6 +186,7 @@ interface StreamAgentChatOpts {
|
|
|
190
186
|
fallbackCredentialIds?: string[]
|
|
191
187
|
signal?: AbortSignal
|
|
192
188
|
promptMode?: PromptMode
|
|
189
|
+
classification?: MessageClassification | null
|
|
193
190
|
/** Run source (e.g. 'heartbeat', 'chat', 'scheduler') — used for heartbeat-specific tuning. */
|
|
194
191
|
source?: string
|
|
195
192
|
}
|
|
@@ -223,10 +220,23 @@ export async function streamAgentChat(opts: StreamAgentChatOpts): Promise<Stream
|
|
|
223
220
|
|
|
224
221
|
async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAgentChatResult> {
|
|
225
222
|
const startTs = Date.now()
|
|
226
|
-
const {
|
|
223
|
+
const {
|
|
224
|
+
session,
|
|
225
|
+
message,
|
|
226
|
+
imagePath,
|
|
227
|
+
imageUrl,
|
|
228
|
+
attachedFiles,
|
|
229
|
+
apiKey,
|
|
230
|
+
systemPrompt,
|
|
231
|
+
executionBrief,
|
|
232
|
+
extraSystemContext,
|
|
233
|
+
write,
|
|
234
|
+
history,
|
|
235
|
+
fallbackCredentialIds,
|
|
236
|
+
signal,
|
|
237
|
+
classification: providedClassification,
|
|
238
|
+
} = opts
|
|
227
239
|
const isHeartbeat = isHeartbeatSource(opts.source)
|
|
228
|
-
const promptMode: PromptMode = opts.promptMode ?? resolvePromptMode(session)
|
|
229
|
-
const isMinimalPrompt = promptMode === 'minimal'
|
|
230
240
|
const isConnectorSession = isDirectConnectorSession(session)
|
|
231
241
|
const rawExtensions = getEnabledCapabilityIds(session)
|
|
232
242
|
const hasShellCapability = rawExtensions.some((toolId) => ['shell', 'execute_command'].includes(String(toolId)))
|
|
@@ -241,6 +251,23 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
241
251
|
|
|
242
252
|
const sessionAgent = session.agentId ? getAgent(session.agentId) : null
|
|
243
253
|
|
|
254
|
+
const classificationPromise = providedClassification !== undefined
|
|
255
|
+
? Promise.resolve(providedClassification)
|
|
256
|
+
: classifyMessage({
|
|
257
|
+
sessionId: session.id,
|
|
258
|
+
agentId: session.agentId,
|
|
259
|
+
message,
|
|
260
|
+
history,
|
|
261
|
+
}).catch(() => null as MessageClassification | null)
|
|
262
|
+
const classification = await classificationPromise
|
|
263
|
+
const lightweightDirectChat = classification?.isLightweightDirectChat === true
|
|
264
|
+
&& !isConnectorSession
|
|
265
|
+
&& !isHeartbeat
|
|
266
|
+
const promptMode: PromptMode = opts.promptMode ?? resolvePromptMode(session, {
|
|
267
|
+
preferMinimalPrompt: lightweightDirectChat,
|
|
268
|
+
})
|
|
269
|
+
const isMinimalPrompt = promptMode === 'minimal'
|
|
270
|
+
|
|
244
271
|
// Resolve agent's thinking level for provider-native params
|
|
245
272
|
let agentThinkingLevel: 'minimal' | 'low' | 'medium' | 'high' | undefined
|
|
246
273
|
if (session.thinkingLevel) {
|
|
@@ -248,6 +275,9 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
248
275
|
} else if (sessionAgent) {
|
|
249
276
|
agentThinkingLevel = sessionAgent.thinkingLevel
|
|
250
277
|
}
|
|
278
|
+
if (lightweightDirectChat) {
|
|
279
|
+
agentThinkingLevel = 'minimal'
|
|
280
|
+
}
|
|
251
281
|
|
|
252
282
|
const llm = buildChatModel({
|
|
253
283
|
provider: session.provider,
|
|
@@ -296,16 +326,6 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
296
326
|
return Math.max(0, Math.min(3600, Math.trunc(parsed)))
|
|
297
327
|
})()
|
|
298
328
|
|
|
299
|
-
// -------------------------------------------------------------------------
|
|
300
|
-
// Start message classification in the background (LLM-based, ~200-800ms)
|
|
301
|
-
// -------------------------------------------------------------------------
|
|
302
|
-
const classificationPromise = classifyMessage({
|
|
303
|
-
sessionId: session.id,
|
|
304
|
-
agentId: session.agentId,
|
|
305
|
-
message,
|
|
306
|
-
history,
|
|
307
|
-
}).catch(() => null as MessageClassification | null)
|
|
308
|
-
|
|
309
329
|
// -------------------------------------------------------------------------
|
|
310
330
|
// System prompt assembly (stays inline — many async calls + local state)
|
|
311
331
|
// -------------------------------------------------------------------------
|
|
@@ -426,8 +446,6 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
426
446
|
const suggestionsBlock = buildSuggestionsSection(settings.suggestionsEnabled, isMinimalPrompt)
|
|
427
447
|
if (suggestionsBlock) promptParts.push(suggestionsBlock)
|
|
428
448
|
|
|
429
|
-
// Await classification before building the agentic execution policy
|
|
430
|
-
const classification = await classificationPromise
|
|
431
449
|
const delegationAdvisory = sessionAgent && agentDelegationEnabled
|
|
432
450
|
? resolveDelegationAdvisory({
|
|
433
451
|
currentAgent: sessionAgent,
|
|
@@ -867,7 +885,7 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
867
885
|
const routingDecision = routeTaskIntent(message, sessionExtensions, null, classification)
|
|
868
886
|
const explicitRequiredToolNames = getExplicitRequiredToolNames(message, sessionExtensions)
|
|
869
887
|
|
|
870
|
-
const boundedExternalExecutionTask =
|
|
888
|
+
const boundedExternalExecutionTask = false
|
|
871
889
|
const likelyResearchSynthesisTask = classifiedIsResearchSynthesis(classification, routingDecision.intent)
|
|
872
890
|
const shouldEnforceEarlyRequiredToolKickoff = explicitRequiredToolNames.length > 0
|
|
873
891
|
&& classifiedIsDeliverableTask(classification, message)
|
|
@@ -1138,7 +1156,14 @@ async function streamAgentChatCore(opts: StreamAgentChatOpts): Promise<StreamAge
|
|
|
1138
1156
|
}
|
|
1139
1157
|
|
|
1140
1158
|
// Async LLM-based incomplete-action check: catches "I'll run the deployment:" with no tool calls
|
|
1141
|
-
if (
|
|
1159
|
+
if (
|
|
1160
|
+
!shouldContinue
|
|
1161
|
+
&& outcome
|
|
1162
|
+
&& !state.hasToolCalls
|
|
1163
|
+
&& classification?.isLightweightDirectChat !== true
|
|
1164
|
+
&& state.fullText.trim().length > 0
|
|
1165
|
+
&& state.fullText.trim().length < 500
|
|
1166
|
+
) {
|
|
1142
1167
|
const completeness = await evaluateResponseCompleteness({
|
|
1143
1168
|
sessionId: session.id,
|
|
1144
1169
|
agentId: session.agentId,
|
|
@@ -46,36 +46,6 @@ describe('stream-continuation', () => {
|
|
|
46
46
|
})
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
// ---- looksLikeExternalWalletTask ----
|
|
50
|
-
describe('looksLikeExternalWalletTask', () => {
|
|
51
|
-
it('matches wallet keywords', () => {
|
|
52
|
-
assert.equal(mod.looksLikeExternalWalletTask('swap 100 USDC on Arbitrum'), true)
|
|
53
|
-
assert.equal(mod.looksLikeExternalWalletTask('check my wallet balance'), true)
|
|
54
|
-
assert.equal(mod.looksLikeExternalWalletTask('trade ETH for SOL'), true)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('returns false for empty/unrelated text', () => {
|
|
58
|
-
assert.equal(mod.looksLikeExternalWalletTask(''), false)
|
|
59
|
-
assert.equal(mod.looksLikeExternalWalletTask('write me a poem about cats'), false)
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// ---- looksLikeBoundedExternalExecutionTask ----
|
|
64
|
-
describe('looksLikeBoundedExternalExecutionTask', () => {
|
|
65
|
-
it('requires wallet keywords + action verbs', () => {
|
|
66
|
-
assert.equal(mod.looksLikeBoundedExternalExecutionTask('swap 100 USDC on Arbitrum'), true)
|
|
67
|
-
assert.equal(mod.looksLikeBoundedExternalExecutionTask('buy ETH on the exchange'), true)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it('returns false without action verbs', () => {
|
|
71
|
-
assert.equal(mod.looksLikeBoundedExternalExecutionTask('check my wallet balance'), false)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('returns false for non-wallet text', () => {
|
|
75
|
-
assert.equal(mod.looksLikeBoundedExternalExecutionTask('execute the test suite'), false)
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
|
|
79
49
|
// ---- looksLikeOpenEndedDeliverableTask ----
|
|
80
50
|
describe('looksLikeOpenEndedDeliverableTask', () => {
|
|
81
51
|
it('matches deliverable patterns', () => {
|
|
@@ -112,24 +82,6 @@ describe('stream-continuation', () => {
|
|
|
112
82
|
})
|
|
113
83
|
})
|
|
114
84
|
|
|
115
|
-
// ---- hasStateChangingWalletEvidence ----
|
|
116
|
-
describe('hasStateChangingWalletEvidence', () => {
|
|
117
|
-
it('detects send_transaction action in wallet_tool', () => {
|
|
118
|
-
const events = [{ name: 'wallet_tool', input: '{"action":"send_transaction"}', output: '{}' }]
|
|
119
|
-
assert.equal(mod.hasStateChangingWalletEvidence(events), true)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('returns false for non-wallet tools', () => {
|
|
123
|
-
const events = [{ name: 'web', input: 'search', output: 'results' }]
|
|
124
|
-
assert.equal(mod.hasStateChangingWalletEvidence(events), false)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('returns false for read-only wallet actions', () => {
|
|
128
|
-
const events = [{ name: 'wallet_tool', input: '{"action":"balance"}', output: '{}' }]
|
|
129
|
-
assert.equal(mod.hasStateChangingWalletEvidence(events), false)
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
|
|
133
85
|
// ---- countExternalExecutionResearchSteps ----
|
|
134
86
|
describe('countExternalExecutionResearchSteps', () => {
|
|
135
87
|
it('counts http/web/browser tools', () => {
|
|
@@ -141,12 +93,12 @@ describe('stream-continuation', () => {
|
|
|
141
93
|
assert.equal(mod.countExternalExecutionResearchSteps(events), 2)
|
|
142
94
|
})
|
|
143
95
|
|
|
144
|
-
it('
|
|
96
|
+
it('does not count non-research tools', () => {
|
|
145
97
|
const events = [
|
|
146
|
-
{ name: '
|
|
147
|
-
{ name: '
|
|
98
|
+
{ name: 'shell', input: 'ls', output: 'files' },
|
|
99
|
+
{ name: 'files', input: 'read', output: 'content' },
|
|
148
100
|
]
|
|
149
|
-
assert.equal(mod.countExternalExecutionResearchSteps(events),
|
|
101
|
+
assert.equal(mod.countExternalExecutionResearchSteps(events), 0)
|
|
150
102
|
})
|
|
151
103
|
})
|
|
152
104
|
|
|
@@ -194,25 +194,9 @@ function getRequestedArtifactStatus(params: {
|
|
|
194
194
|
// Tool evidence analysis
|
|
195
195
|
// ---------------------------------------------------------------------------
|
|
196
196
|
|
|
197
|
-
export function hasStateChangingWalletEvidence(toolEvents: MessageToolEvent[]): boolean {
|
|
198
|
-
return toolEvents.some((event) => {
|
|
199
|
-
const input = `${event.input || ''}\n${event.output || ''}`
|
|
200
|
-
return event.name === 'wallet_tool' && (
|
|
201
|
-
/"action":"send_transaction"/.test(input)
|
|
202
|
-
|| /"action":"send"/.test(input)
|
|
203
|
-
|| /"action":"sign_transaction"/.test(input)
|
|
204
|
-
|| /"type":"extension_wallet_action_request"/.test(input)
|
|
205
|
-
|| /"type":"extension_wallet_transfer_request"/.test(input)
|
|
206
|
-
|| /"status":"broadcast"/.test(input)
|
|
207
|
-
)
|
|
208
|
-
})
|
|
209
|
-
}
|
|
210
|
-
|
|
211
197
|
export function countExternalExecutionResearchSteps(toolEvents: MessageToolEvent[]): number {
|
|
212
198
|
return toolEvents.filter((event) => {
|
|
213
|
-
|
|
214
|
-
if (event.name !== 'wallet_tool') return false
|
|
215
|
-
return /"action":"(balance|address|transactions|call_contract|encode_contract_call)"/.test(event.input || '')
|
|
199
|
+
return ['http_request', 'web', 'web_search', 'web_fetch', 'browser'].includes(event.name)
|
|
216
200
|
}).length
|
|
217
201
|
}
|
|
218
202
|
|
|
@@ -238,49 +222,24 @@ export function countDistinctExternalResearchHosts(toolEvents: MessageToolEvent[
|
|
|
238
222
|
// Continuation decision helpers
|
|
239
223
|
// ---------------------------------------------------------------------------
|
|
240
224
|
|
|
241
|
-
export function shouldForceExternalExecutionFollowthrough(
|
|
225
|
+
export function shouldForceExternalExecutionFollowthrough(_params: {
|
|
242
226
|
userMessage: string
|
|
243
227
|
finalResponse: string
|
|
244
228
|
hasToolCalls: boolean
|
|
245
229
|
toolEvents: MessageToolEvent[]
|
|
246
230
|
classification?: MessageClassification | null
|
|
247
231
|
}): boolean {
|
|
248
|
-
|
|
249
|
-
if (!isTransactional) return false
|
|
250
|
-
if (!params.hasToolCalls || params.toolEvents.length < 4) return false
|
|
251
|
-
if (hasStateChangingWalletEvidence(params.toolEvents)) return false
|
|
252
|
-
const distinctHosts = countDistinctExternalResearchHosts(params.toolEvents)
|
|
253
|
-
const trimmed = params.finalResponse.trim()
|
|
254
|
-
if (!trimmed) return countExternalExecutionResearchSteps(params.toolEvents) >= 4 || distinctHosts >= 3
|
|
255
|
-
if (/\b(last reversible step|exact blocker|safest next action|blocked|cannot|can't|missing capability|no-key route unavailable)\b/i.test(trimmed)) {
|
|
256
|
-
return false
|
|
257
|
-
}
|
|
258
|
-
if (countExternalExecutionResearchSteps(params.toolEvents) < 4 && distinctHosts < 3) return false
|
|
259
|
-
return /(let me|i'll|i will|trying|research|query|check|look|promising|now let me|good -|good,)/i.test(trimmed) || trimmed.length < 500
|
|
232
|
+
return false
|
|
260
233
|
}
|
|
261
234
|
|
|
262
|
-
export function shouldForceExternalExecutionKickoffFollowthrough(
|
|
235
|
+
export function shouldForceExternalExecutionKickoffFollowthrough(_params: {
|
|
263
236
|
userMessage: string
|
|
264
237
|
finalResponse: string
|
|
265
238
|
hasToolCalls: boolean
|
|
266
239
|
toolEvents: MessageToolEvent[]
|
|
267
240
|
classification?: MessageClassification | null
|
|
268
241
|
}): boolean {
|
|
269
|
-
|
|
270
|
-
if (!isTransactional) return false
|
|
271
|
-
if (params.hasToolCalls || params.toolEvents.length > 0) return false
|
|
272
|
-
|
|
273
|
-
const trimmed = params.finalResponse.trim()
|
|
274
|
-
if (!trimmed) return true
|
|
275
|
-
if (/^(?:HEARTBEAT_OK|NO_MESSAGE)\b/i.test(trimmed)) return false
|
|
276
|
-
if (/\?\s*$/.test(trimmed)) return false
|
|
277
|
-
if (/\b(last reversible step|exact blocker|blocked|cannot|can't|missing capability|need approval|requires approval|approval boundary|requires human|ask_human|credential|authentication|login|2fa|mfa|captcha)\b/i.test(trimmed)) {
|
|
278
|
-
return false
|
|
279
|
-
}
|
|
280
|
-
if (/\b(done|completed|finished|sent|broadcast|minted|purchased|bought|swapped|claimed)\b/i.test(trimmed)) {
|
|
281
|
-
return false
|
|
282
|
-
}
|
|
283
|
-
return looksLikeIncompleteDeliverableResponse(trimmed) || trimmed.length < 220
|
|
242
|
+
return false
|
|
284
243
|
}
|
|
285
244
|
|
|
286
245
|
export function shouldForceDeliverableFollowthrough(params: {
|
|
@@ -454,8 +413,7 @@ function buildExternalExecutionFollowthroughPrompt(params: {
|
|
|
454
413
|
'You are in a bounded external execution task and have already done enough research.',
|
|
455
414
|
'Do not restart broad discovery. Do not ask the user for another prompt.',
|
|
456
415
|
'Do not spend this continuation on more venue shopping. Use the already confirmed route unless one last fetch is strictly required to prepare execution.',
|
|
457
|
-
'If several venue or aggregator APIs already failed, stop searching for more venues
|
|
458
|
-
'A prose approval request does not count as completion. If the next step is a sign/send/approve action, call the real wallet tool action so the runtime can create the approval request.',
|
|
416
|
+
'If several venue or aggregator APIs already failed, stop searching for more venues and state the blocker.',
|
|
459
417
|
'Do not mutate already confirmed token addresses, router addresses, spender addresses, or network identifiers unless newer tool evidence proves the earlier value was wrong.',
|
|
460
418
|
'Within this continuation, do exactly one of the following:',
|
|
461
419
|
'1. Take the next concrete execution step now using the existing tools and stop at the first approval boundary for a state-changing action.',
|
|
@@ -16,6 +16,8 @@ const agents: Record<string, Agent> = {
|
|
|
16
16
|
model: 'gpt-test',
|
|
17
17
|
systemPrompt: '',
|
|
18
18
|
capabilities: ['deploy', 'infrastructure'],
|
|
19
|
+
createdAt: Date.now(),
|
|
20
|
+
updatedAt: Date.now(),
|
|
19
21
|
},
|
|
20
22
|
design: {
|
|
21
23
|
id: 'design',
|
|
@@ -25,6 +27,8 @@ const agents: Record<string, Agent> = {
|
|
|
25
27
|
model: 'gpt-test',
|
|
26
28
|
systemPrompt: '',
|
|
27
29
|
capabilities: ['design', 'ui'],
|
|
30
|
+
createdAt: Date.now(),
|
|
31
|
+
updatedAt: Date.now(),
|
|
28
32
|
},
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { genId } from '@/lib/id'
|
|
2
2
|
import type { MailboxEnvelope } from '@/types'
|
|
3
3
|
import { loadSession, patchSession } from '@/lib/server/sessions/session-repository'
|
|
4
|
-
import { requestMissionTicksForHumanReply } from '@/lib/server/missions/mission-service'
|
|
5
4
|
|
|
6
5
|
interface MailboxOptions {
|
|
7
6
|
limit?: number
|
|
@@ -167,15 +166,6 @@ export function sendMailboxEnvelope(input: {
|
|
|
167
166
|
lastActiveAt: now,
|
|
168
167
|
}
|
|
169
168
|
})
|
|
170
|
-
if (envelope.type === 'human_reply') {
|
|
171
|
-
requestMissionTicksForHumanReply({
|
|
172
|
-
sessionId: input.toSessionId,
|
|
173
|
-
correlationId: envelope.correlationId || null,
|
|
174
|
-
envelopeId: envelope.id,
|
|
175
|
-
payload: envelope.payload,
|
|
176
|
-
fromSessionId: envelope.fromSessionId || null,
|
|
177
|
-
})
|
|
178
|
-
}
|
|
179
169
|
import('@/lib/server/runtime/watch-jobs')
|
|
180
170
|
.then(({ triggerMailboxWatchJobs }) => {
|
|
181
171
|
triggerMailboxWatchJobs({ sessionId: input.toSessionId, envelope })
|
|
@@ -7,7 +7,6 @@ import { buildAgentDisabledMessage, isAgentDisabled } from '@/lib/server/agents/
|
|
|
7
7
|
import { loadAgent } from '@/lib/server/agents/agent-repository'
|
|
8
8
|
import { clearMainLoopStateForSession } from '@/lib/server/agents/main-agent-loop'
|
|
9
9
|
import { applyResolvedRoute, resolvePrimaryAgentRoute } from '@/lib/server/agents/agent-runtime-config'
|
|
10
|
-
import { enrichSessionWithMissionSummary } from '@/lib/server/missions/mission-service'
|
|
11
10
|
import { cleanupSessionProcesses } from '@/lib/server/runtime/process-manager'
|
|
12
11
|
import { stopActiveSessionProcess } from '@/lib/server/runtime/runtime-state'
|
|
13
12
|
import {
|
|
@@ -60,7 +59,7 @@ export function listChatsForApi(): Record<string, ReturnType<typeof buildSession
|
|
|
60
59
|
sessions[id].currentRunId = run.runningRunId || null
|
|
61
60
|
}
|
|
62
61
|
return Object.fromEntries(
|
|
63
|
-
Object.entries(sessions).map(([id, session]) => [id, buildSessionListSummary(
|
|
62
|
+
Object.entries(sessions).map(([id, session]) => [id, buildSessionListSummary(session)]),
|
|
64
63
|
)
|
|
65
64
|
}
|
|
66
65
|
|
|
@@ -72,7 +71,7 @@ export function getChatSessionForApi(sessionId: string): Session | null {
|
|
|
72
71
|
session.active = !!run.runningRunId
|
|
73
72
|
session.queuedCount = queue.queueLength
|
|
74
73
|
session.currentRunId = run.runningRunId || null
|
|
75
|
-
return
|
|
74
|
+
return session
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
export function createChatSession(input: Record<string, unknown>): ServiceResult<Session> {
|
|
@@ -285,7 +284,7 @@ export function updateChatSession(sessionId: string, updates: Record<string, unk
|
|
|
285
284
|
|
|
286
285
|
saveSession(sessionId, original)
|
|
287
286
|
notify('sessions')
|
|
288
|
-
return
|
|
287
|
+
return original
|
|
289
288
|
}
|
|
290
289
|
|
|
291
290
|
export function deleteChatSession(sessionId: string): boolean {
|
|
@@ -320,7 +319,6 @@ export function queueChatMessage(sessionId: string, body: Record<string, unknown
|
|
|
320
319
|
}
|
|
321
320
|
const queued = enqueueSessionRun({
|
|
322
321
|
sessionId,
|
|
323
|
-
missionId: session.missionId || null,
|
|
324
322
|
message,
|
|
325
323
|
imagePath,
|
|
326
324
|
imageUrl,
|
|
@@ -1095,7 +1095,6 @@ If media sending fails, report the exact error and retry with a corrected path/t
|
|
|
1095
1095
|
|
|
1096
1096
|
const queued = enqueueSessionRun({
|
|
1097
1097
|
sessionId: session.id,
|
|
1098
|
-
missionId: session.missionId || null,
|
|
1099
1098
|
message: modelInputText,
|
|
1100
1099
|
imagePath: firstImagePath,
|
|
1101
1100
|
imageUrl: firstImageUrl,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
setReconnectState,
|
|
20
20
|
} from './reconnect-state'
|
|
21
21
|
import { connectorRuntimeState, runningConnectors } from './runtime-state'
|
|
22
|
+
import { ensureSwarmdockConnectorCredential } from './swarmdock-secret'
|
|
22
23
|
|
|
23
24
|
const TAG = 'connector-lifecycle'
|
|
24
25
|
|
|
@@ -70,6 +71,7 @@ export async function getPlatform(platform: string) {
|
|
|
70
71
|
case 'googlechat': return (await import('./googlechat')).default
|
|
71
72
|
case 'matrix': return (await import('./matrix')).default
|
|
72
73
|
case 'email': return (await import('./email')).default
|
|
74
|
+
case 'swarmdock': return (await import('./swarmdock')).default
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
// 2. Check Extension-provided connectors
|
|
@@ -134,8 +136,9 @@ async function _startConnectorImpl(connectorId: string): Promise<void> {
|
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
const connectors = loadConnectors()
|
|
137
|
-
const
|
|
138
|
-
if (!
|
|
139
|
+
const storedConnector = connectors[connectorId] as Connector | undefined
|
|
140
|
+
if (!storedConnector) throw new Error('Connector not found')
|
|
141
|
+
let connector: Connector = storedConnector
|
|
139
142
|
|
|
140
143
|
// Starting a connector expresses durable intent: keep it enabled across
|
|
141
144
|
// transient failures so daemon recovery and server restarts can retry it.
|
|
@@ -148,6 +151,16 @@ async function _startConnectorImpl(connectorId: string): Promise<void> {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
try {
|
|
154
|
+
let swarmdockFallbackPrivateKey: string | null = null
|
|
155
|
+
if (connector.platform === 'swarmdock') {
|
|
156
|
+
const prepared = ensureSwarmdockConnectorCredential(connector, {
|
|
157
|
+
allowMigrationFailureFallback: true,
|
|
158
|
+
})
|
|
159
|
+
connector = prepared.connector
|
|
160
|
+
connectors[connectorId] = connector
|
|
161
|
+
swarmdockFallbackPrivateKey = prepared.fallbackPrivateKey
|
|
162
|
+
}
|
|
163
|
+
|
|
151
164
|
// Resolve bot token from credential
|
|
152
165
|
let botToken = ''
|
|
153
166
|
if (connector.credentialId) {
|
|
@@ -164,8 +177,11 @@ async function _startConnectorImpl(connectorId: string): Promise<void> {
|
|
|
164
177
|
if (!botToken && connector.platform === 'bluebubbles' && connector.config.password) {
|
|
165
178
|
botToken = connector.config.password
|
|
166
179
|
}
|
|
180
|
+
if (!botToken && swarmdockFallbackPrivateKey) {
|
|
181
|
+
botToken = swarmdockFallbackPrivateKey
|
|
182
|
+
}
|
|
167
183
|
|
|
168
|
-
if (!botToken && connector.platform !== 'whatsapp' && connector.platform !== 'openclaw' && connector.platform !== 'signal' && connector.platform !== 'email') {
|
|
184
|
+
if (!botToken && connector.platform !== 'whatsapp' && connector.platform !== 'openclaw' && connector.platform !== 'signal' && connector.platform !== 'email' && connector.platform !== 'swarmdock') {
|
|
169
185
|
throw new Error('No bot token configured')
|
|
170
186
|
}
|
|
171
187
|
|
|
@@ -43,6 +43,11 @@ import type {
|
|
|
43
43
|
} from '@/types'
|
|
44
44
|
import type { ServiceResult } from '@/lib/server/service-result'
|
|
45
45
|
import type { DaemonConnectorRuntimeState } from '@/lib/server/daemon/types'
|
|
46
|
+
import {
|
|
47
|
+
ensureSwarmdockConnectorCredential,
|
|
48
|
+
prepareSwarmdockConnectorInput,
|
|
49
|
+
redactConnectorSecrets,
|
|
50
|
+
} from './swarmdock-secret'
|
|
46
51
|
|
|
47
52
|
function cloneConnector<T extends Connector>(connector: T): T {
|
|
48
53
|
return {
|
|
@@ -124,35 +129,52 @@ function requireSenderId(body: Record<string, unknown>): string {
|
|
|
124
129
|
export async function listConnectorsWithRuntime(): Promise<Record<string, Connector>> {
|
|
125
130
|
await ensureDaemonProcessRunning('api/connectors:get')
|
|
126
131
|
const connectors = Object.fromEntries(
|
|
127
|
-
Object.entries(loadConnectors()).map(([id, connector]) =>
|
|
132
|
+
Object.entries(loadConnectors()).map(([id, connector]) => {
|
|
133
|
+
const prepared = ensureSwarmdockConnectorCredential(connector, {
|
|
134
|
+
allowMigrationFailureFallback: true,
|
|
135
|
+
})
|
|
136
|
+
return [id, cloneConnector(prepared.connector)]
|
|
137
|
+
}),
|
|
128
138
|
) as Record<string, Connector>
|
|
129
139
|
const runtimeByConnector = await listDaemonConnectorRuntime()
|
|
130
140
|
for (const connector of Object.values(connectors)) {
|
|
131
141
|
applyRuntimeFields(connector, runtimeByConnector[connector.id] || null)
|
|
132
142
|
}
|
|
133
|
-
return
|
|
143
|
+
return Object.fromEntries(
|
|
144
|
+
Object.entries(connectors).map(([id, connector]) => [id, redactConnectorSecrets(connector)]),
|
|
145
|
+
)
|
|
134
146
|
}
|
|
135
147
|
|
|
136
148
|
export async function getConnectorWithRuntime(id: string): Promise<Connector | null> {
|
|
137
149
|
await ensureDaemonProcessRunning('api/connectors/[id]:get')
|
|
138
150
|
const connector = loadConnector(id)
|
|
139
151
|
if (!connector) return null
|
|
140
|
-
const
|
|
141
|
-
|
|
152
|
+
const prepared = ensureSwarmdockConnectorCredential(connector, {
|
|
153
|
+
allowMigrationFailureFallback: true,
|
|
154
|
+
})
|
|
155
|
+
const current = cloneConnector(prepared.connector)
|
|
156
|
+
return redactConnectorSecrets(applyRuntimeFields(current, await getDaemonConnectorRuntime(id)))
|
|
142
157
|
}
|
|
143
158
|
|
|
144
159
|
export function createConnector(body: Record<string, unknown>): Connector {
|
|
145
160
|
const id = genId()
|
|
161
|
+
const rawConfig = body.config && typeof body.config === 'object' && !Array.isArray(body.config)
|
|
162
|
+
? body.config as Record<string, string>
|
|
163
|
+
: {}
|
|
164
|
+
const prepared = prepareSwarmdockConnectorInput({
|
|
165
|
+
platform: body.platform as Connector['platform'],
|
|
166
|
+
name: (body.name as string) || `${String(body.platform || '')} Connector`,
|
|
167
|
+
credentialId: (body.credentialId as string | null | undefined) || null,
|
|
168
|
+
config: rawConfig,
|
|
169
|
+
})
|
|
146
170
|
const connector: Connector = {
|
|
147
171
|
id,
|
|
148
172
|
name: (body.name as string) || `${String(body.platform || '')} Connector`,
|
|
149
173
|
platform: body.platform as Connector['platform'],
|
|
150
174
|
agentId: (body.agentId as string | null | undefined) || null,
|
|
151
175
|
chatroomId: (body.chatroomId as string | null | undefined) || null,
|
|
152
|
-
credentialId:
|
|
153
|
-
config:
|
|
154
|
-
? body.config as Record<string, string>
|
|
155
|
-
: {},
|
|
176
|
+
credentialId: prepared.credentialId,
|
|
177
|
+
config: prepared.config,
|
|
156
178
|
isEnabled: false,
|
|
157
179
|
status: 'stopped',
|
|
158
180
|
lastError: null,
|
|
@@ -210,6 +232,14 @@ export async function updateConnectorFromRoute(id: string, body: Record<string,
|
|
|
210
232
|
if (body.credentialId !== undefined) next.credentialId = typeof body.credentialId === 'string' || body.credentialId === null ? body.credentialId : next.credentialId
|
|
211
233
|
if (body.config !== undefined) next.config = body.config && typeof body.config === 'object' && !Array.isArray(body.config) ? body.config as Record<string, string> : next.config
|
|
212
234
|
if (body.isEnabled !== undefined) next.isEnabled = typeof body.isEnabled === 'boolean' ? body.isEnabled : next.isEnabled
|
|
235
|
+
const prepared = prepareSwarmdockConnectorInput({
|
|
236
|
+
platform: next.platform,
|
|
237
|
+
name: next.name,
|
|
238
|
+
credentialId: next.credentialId || null,
|
|
239
|
+
config: next.config,
|
|
240
|
+
})
|
|
241
|
+
next.credentialId = prepared.credentialId
|
|
242
|
+
next.config = prepared.config
|
|
213
243
|
persistConnector(next)
|
|
214
244
|
|
|
215
245
|
try {
|
|
@@ -235,7 +265,7 @@ export async function updateConnectorFromRoute(id: string, body: Record<string,
|
|
|
235
265
|
}
|
|
236
266
|
|
|
237
267
|
notify('connectors')
|
|
238
|
-
return serviceOk(await getConnectorWithRuntime(id) || next)
|
|
268
|
+
return serviceOk(await getConnectorWithRuntime(id) || redactConnectorSecrets(next))
|
|
239
269
|
}
|
|
240
270
|
|
|
241
271
|
export async function deleteConnectorFromRoute(id: string): Promise<ServiceResult<{ ok: true }>> {
|
|
@@ -217,8 +217,8 @@ const discord: PlatformConnector = {
|
|
|
217
217
|
return String(sent.id || '')
|
|
218
218
|
},
|
|
219
219
|
})
|
|
220
|
-
} catch (err:
|
|
221
|
-
log.error(TAG, 'Error handling message:', err
|
|
220
|
+
} catch (err: unknown) {
|
|
221
|
+
log.error(TAG, 'Error handling message:', errorMessage(err))
|
|
222
222
|
try {
|
|
223
223
|
await message.reply('Sorry, I encountered an error processing your message.')
|
|
224
224
|
} catch { /* ignore */ }
|
|
@@ -4,6 +4,7 @@ import path from 'path'
|
|
|
4
4
|
import { DATA_DIR } from '../data-dir'
|
|
5
5
|
import type { PlatformConnector, ConnectorInstance, InboundMessage } from './types'
|
|
6
6
|
import { resolveConnectorIngressReply } from './ingress-delivery'
|
|
7
|
+
import { errorMessage } from '@/lib/shared-utils'
|
|
7
8
|
|
|
8
9
|
const TAG = 'matrix'
|
|
9
10
|
|
|
@@ -54,8 +55,8 @@ const matrix: PlatformConnector = {
|
|
|
54
55
|
const reply = await resolveConnectorIngressReply(onMessage, inbound)
|
|
55
56
|
if (!reply) return
|
|
56
57
|
await client.sendText(roomId, reply.visibleText)
|
|
57
|
-
} catch (err:
|
|
58
|
-
log.error(TAG, 'Error handling message:', err
|
|
58
|
+
} catch (err: unknown) {
|
|
59
|
+
log.error(TAG, 'Error handling message:', errorMessage(err))
|
|
59
60
|
try {
|
|
60
61
|
await client.sendText(roomId, 'Sorry, I encountered an error processing your message.')
|
|
61
62
|
} catch { /* ignore */ }
|
|
@@ -4,6 +4,7 @@ import type { ChildProcess } from 'child_process'
|
|
|
4
4
|
import type { Connector } from '@/types'
|
|
5
5
|
import type { PlatformConnector, ConnectorInstance, InboundMessage, ConnectorIngressResult } from './types'
|
|
6
6
|
import { resolveConnectorIngressReply } from './ingress-delivery'
|
|
7
|
+
import { errorMessage } from '@/lib/shared-utils'
|
|
7
8
|
|
|
8
9
|
const TAG = 'signal'
|
|
9
10
|
|
|
@@ -107,8 +108,8 @@ const signal: PlatformConnector = {
|
|
|
107
108
|
`${cliPath} -u ${phoneNumber} send -m ${JSON.stringify(text)} ${channelId}`,
|
|
108
109
|
{ timeout: 15_000 },
|
|
109
110
|
)
|
|
110
|
-
} catch (err:
|
|
111
|
-
throw new Error(`Signal send failed: ${err
|
|
111
|
+
} catch (err: unknown) {
|
|
112
|
+
throw new Error(`Signal send failed: ${errorMessage(err)}`)
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
},
|
|
@@ -179,8 +180,8 @@ export async function handleSignalEvent(
|
|
|
179
180
|
{ timeout: 15_000 },
|
|
180
181
|
)
|
|
181
182
|
}
|
|
182
|
-
} catch (err:
|
|
183
|
-
log.error(TAG, 'Error handling message:', err
|
|
183
|
+
} catch (err: unknown) {
|
|
184
|
+
log.error(TAG, 'Error handling message:', errorMessage(err))
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
|