@swarmclawai/swarmclaw 1.2.4 → 1.2.6
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 +14 -0
- package/bin/daemon-cmd.js +169 -0
- package/bin/server-cmd.js +3 -0
- package/bin/swarmclaw.js +11 -0
- package/package.json +17 -16
- package/src/app/api/agents/[id]/clone/route.ts +3 -32
- package/src/app/api/agents/[id]/route.ts +6 -158
- package/src/app/api/agents/[id]/status/route.ts +2 -3
- package/src/app/api/agents/[id]/thread/route.ts +4 -17
- package/src/app/api/agents/bulk/route.ts +5 -47
- package/src/app/api/agents/route.ts +5 -119
- package/src/app/api/agents/trash/route.ts +13 -24
- package/src/app/api/auth/route.ts +3 -9
- package/src/app/api/autonomy/estop/route.ts +5 -5
- package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
- package/src/app/api/chatrooms/[id]/route.ts +23 -2
- package/src/app/api/chatrooms/route.ts +13 -2
- package/src/app/api/chats/[id]/clear/route.ts +2 -13
- package/src/app/api/chats/[id]/deploy/route.ts +2 -3
- package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
- package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
- package/src/app/api/chats/[id]/queue/route.ts +17 -64
- package/src/app/api/chats/[id]/retry/route.ts +4 -22
- package/src/app/api/chats/[id]/route.ts +10 -138
- package/src/app/api/chats/heartbeat/route.ts +2 -1
- package/src/app/api/chats/migrate-messages/route.ts +7 -0
- package/src/app/api/chats/route.ts +13 -134
- package/src/app/api/connectors/[id]/access/route.ts +12 -229
- package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
- package/src/app/api/connectors/[id]/health/route.ts +12 -39
- package/src/app/api/connectors/[id]/route.ts +14 -122
- package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
- package/src/app/api/connectors/doctor/route.ts +1 -1
- package/src/app/api/connectors/route.ts +12 -70
- package/src/app/api/credentials/[id]/route.ts +2 -4
- package/src/app/api/credentials/route.ts +10 -19
- package/src/app/api/daemon/health-check/route.ts +3 -4
- package/src/app/api/daemon/route.ts +10 -8
- package/src/app/api/documents/route.ts +11 -10
- package/src/app/api/external-agents/route.ts +3 -3
- package/src/app/api/gateways/[id]/health/route.ts +2 -3
- package/src/app/api/gateways/[id]/route.ts +7 -122
- package/src/app/api/gateways/route.ts +3 -103
- package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
- package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
- package/src/app/api/openclaw/directory/route.ts +2 -2
- package/src/app/api/openclaw/history/route.ts +3 -5
- package/src/app/api/providers/[id]/route.test.ts +49 -0
- package/src/app/api/providers/ollama/route.ts +6 -5
- package/src/app/api/schedules/[id]/route.ts +14 -108
- package/src/app/api/schedules/[id]/run/route.ts +6 -67
- package/src/app/api/schedules/route.ts +9 -51
- package/src/app/api/settings/route.ts +4 -3
- package/src/app/api/setup/check-provider/route.ts +23 -1
- package/src/app/api/setup/openclaw-device/route.ts +2 -2
- package/src/app/api/system/status/route.ts +2 -2
- package/src/app/api/tasks/[id]/route.ts +16 -202
- package/src/app/api/tasks/bulk/route.ts +5 -86
- package/src/app/api/tasks/metrics/route.ts +2 -1
- package/src/app/api/tasks/route.ts +11 -171
- package/src/app/api/upload/route.ts +1 -1
- package/src/app/api/uploads/[filename]/route.ts +1 -1
- package/src/app/api/uploads/route.ts +1 -1
- package/src/app/api/webhooks/[id]/history/route.ts +2 -2
- package/src/app/layout.tsx +9 -6
- package/src/app/protocols/page.tsx +71 -89
- package/src/app/tasks/page.tsx +32 -32
- package/src/cli/index.js +1 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-sheet.tsx +5 -5
- package/src/components/auth/setup-wizard/index.tsx +4 -4
- package/src/components/auth/setup-wizard/step-agents.tsx +1 -1
- package/src/components/auth/setup-wizard/step-connect.tsx +1 -1
- package/src/components/auth/setup-wizard/utils.ts +1 -1
- package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
- package/src/components/connectors/connector-list.tsx +26 -40
- package/src/components/connectors/connector-sheet.tsx +95 -149
- package/src/components/gateways/gateway-sheet.tsx +61 -110
- package/src/components/layout/live-query-sync.tsx +121 -0
- package/src/components/protocols/structured-session-launcher.tsx +24 -45
- package/src/components/providers/app-query-provider.tsx +17 -0
- package/src/components/providers/provider-list.tsx +60 -61
- package/src/components/providers/provider-sheet.tsx +74 -56
- package/src/components/skills/skill-list.tsx +5 -18
- package/src/components/skills/skill-sheet.tsx +21 -20
- package/src/components/skills/skills-workspace.tsx +48 -87
- package/src/components/tasks/task-card.tsx +20 -13
- package/src/components/tasks/task-column.tsx +22 -7
- package/src/components/tasks/task-list.tsx +8 -11
- package/src/components/tasks/task-sheet.tsx +111 -103
- package/src/features/agents/queries.ts +20 -0
- package/src/features/chatrooms/queries.ts +20 -0
- package/src/features/chats/queries.ts +27 -0
- package/src/features/connectors/queries.ts +145 -0
- package/src/features/credentials/queries.ts +37 -0
- package/src/features/extensions/queries.ts +26 -0
- package/src/features/external-agents/queries.ts +36 -0
- package/src/features/gateways/queries.ts +274 -0
- package/src/features/missions/queries.ts +23 -0
- package/src/features/projects/queries.ts +20 -0
- package/src/features/protocols/queries.ts +149 -0
- package/src/features/providers/queries.ts +142 -0
- package/src/features/settings/queries.ts +20 -0
- package/src/features/skills/queries.ts +182 -0
- package/src/features/tasks/queries.ts +189 -0
- package/src/hooks/use-ws.ts +3 -2
- package/src/lib/app/api-client.ts +2 -2
- package/src/lib/providers/index.test.ts +108 -0
- package/src/lib/providers/index.ts +38 -15
- package/src/lib/query/client.ts +17 -0
- package/src/lib/server/agents/agent-runtime-config.ts +1 -1
- package/src/lib/server/agents/agent-service.ts +429 -0
- package/src/lib/server/agents/agent-thread-session.ts +6 -5
- package/src/lib/server/agents/autonomy-contract.ts +1 -4
- package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
- package/src/lib/server/agents/delegation-advisory.ts +251 -0
- package/src/lib/server/agents/main-agent-loop.ts +98 -40
- package/src/lib/server/agents/subagent-runtime.ts +12 -0
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
- package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
- package/src/lib/server/build-llm.ts +7 -15
- package/src/lib/server/capability-router.test.ts +70 -1
- package/src/lib/server/capability-router.ts +24 -99
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
- package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
- package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
- package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
- package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
- package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
- package/src/lib/server/chat-execution/message-classifier.ts +74 -32
- package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
- package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
- package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
- package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
- package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
- package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
- package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
- package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
- package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
- package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
- package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
- package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
- package/src/lib/server/chats/chat-session-service.ts +410 -0
- package/src/lib/server/connectors/access.ts +1 -1
- package/src/lib/server/connectors/commands.ts +7 -6
- package/src/lib/server/connectors/connector-inbound.ts +14 -7
- package/src/lib/server/connectors/connector-outbound.ts +16 -11
- package/src/lib/server/connectors/connector-service.ts +453 -0
- package/src/lib/server/connectors/delivery.ts +17 -12
- package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
- package/src/lib/server/connectors/media.ts +1 -1
- package/src/lib/server/connectors/response-media.ts +1 -1
- package/src/lib/server/connectors/session-consolidation.ts +11 -7
- package/src/lib/server/connectors/session.ts +9 -7
- package/src/lib/server/connectors/voice-note.ts +2 -1
- package/src/lib/server/context-manager.ts +20 -1
- package/src/lib/server/cost.ts +2 -3
- package/src/lib/server/credentials/credential-repository.ts +43 -4
- package/src/lib/server/credentials/credential-service.ts +112 -0
- package/src/lib/server/daemon/admin-metadata.ts +64 -0
- package/src/lib/server/daemon/controller.ts +577 -0
- package/src/lib/server/daemon/daemon-runtime.ts +352 -0
- package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
- package/src/lib/server/daemon/types.ts +101 -0
- package/src/lib/server/embeddings.ts +3 -9
- package/src/lib/server/eval/agent-regression.ts +3 -2
- package/src/lib/server/eval/runner.ts +2 -2
- package/src/lib/server/execution-brief.test.ts +167 -0
- package/src/lib/server/execution-brief.ts +295 -0
- package/src/lib/server/execution-engine/chat-turn.ts +9 -0
- package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
- package/src/lib/server/execution-engine/index.ts +35 -0
- package/src/lib/server/execution-engine/task-attempt.ts +303 -0
- package/src/lib/server/execution-engine/types.ts +33 -0
- package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
- package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
- package/src/lib/server/memory/session-archive-memory.ts +12 -10
- package/src/lib/server/messages/message-repository.ts +330 -0
- package/src/lib/server/missions/mission-service/core.ts +8 -6
- package/src/lib/server/openclaw/agent-resolver.ts +2 -3
- package/src/lib/server/openclaw/doctor.ts +1 -1
- package/src/lib/server/openclaw/gateway.test.ts +10 -1
- package/src/lib/server/openclaw/gateway.ts +5 -14
- package/src/lib/server/openclaw/health.ts +3 -11
- package/src/lib/server/openclaw/sync.ts +8 -6
- package/src/lib/server/persistence/storage-context.ts +3 -0
- package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
- package/src/lib/server/protocols/protocol-normalization.ts +1 -1
- package/src/lib/server/protocols/protocol-queries.ts +13 -7
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
- package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
- package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
- package/src/lib/server/protocols/protocol-swarm.ts +8 -8
- package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
- package/src/lib/server/protocols/protocol-templates.ts +4 -2
- package/src/lib/server/protocols/protocol-types.ts +10 -7
- package/src/lib/server/provider-endpoint.ts +7 -12
- package/src/lib/server/provider-model-discovery.ts +2 -11
- package/src/lib/server/query-expansion.ts +5 -6
- package/src/lib/server/run-context.test.ts +365 -0
- package/src/lib/server/run-context.ts +367 -0
- package/src/lib/server/runtime/heartbeat-service.ts +7 -5
- package/src/lib/server/runtime/queue/core.ts +61 -190
- package/src/lib/server/runtime/run-ledger.ts +8 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
- package/src/lib/server/schedules/schedule-route-service.ts +230 -0
- package/src/lib/server/service-result.ts +16 -0
- package/src/lib/server/session-note.ts +2 -3
- package/src/lib/server/session-reset-policy.ts +4 -3
- package/src/lib/server/session-tools/connector.ts +9 -6
- package/src/lib/server/session-tools/context-mgmt.ts +58 -9
- package/src/lib/server/session-tools/crud.ts +162 -10
- package/src/lib/server/session-tools/delegate.ts +1 -1
- package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
- package/src/lib/server/session-tools/memory.ts +6 -4
- package/src/lib/server/session-tools/session-info.test.ts +56 -0
- package/src/lib/server/session-tools/session-info.ts +119 -12
- package/src/lib/server/session-tools/skill-runtime.ts +3 -1
- package/src/lib/server/session-tools/skills.ts +15 -15
- package/src/lib/server/session-tools/subagent.test.ts +115 -1
- package/src/lib/server/session-tools/subagent.ts +125 -7
- package/src/lib/server/session-tools/team-context.ts +4 -3
- package/src/lib/server/session-tools/wallet.ts +0 -58
- package/src/lib/server/sessions/session-lineage.ts +55 -0
- package/src/lib/server/sessions/session-repository.ts +2 -2
- package/src/lib/server/skills/learned-skills.ts +24 -23
- package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
- package/src/lib/server/skills/skill-repository.ts +136 -13
- package/src/lib/server/skills/skill-suggestions.ts +25 -28
- package/src/lib/server/storage-normalization.test.ts +44 -267
- package/src/lib/server/storage-normalization.ts +75 -0
- package/src/lib/server/storage.ts +19 -0
- package/src/lib/server/structured-extract.ts +3 -14
- package/src/lib/server/tasks/task-followups.ts +16 -11
- package/src/lib/server/tasks/task-result.test.ts +25 -29
- package/src/lib/server/tasks/task-result.ts +5 -9
- package/src/lib/server/tasks/task-route-service.ts +449 -0
- package/src/lib/server/text-normalization.ts +41 -0
- package/src/lib/server/tool-planning.ts +6 -42
- package/src/lib/server/upload-path.ts +5 -0
- package/src/lib/server/working-state/extraction.ts +614 -0
- package/src/lib/server/working-state/normalization.ts +866 -0
- package/src/lib/server/working-state/prompt.ts +60 -0
- package/src/lib/server/working-state/repository.ts +38 -0
- package/src/lib/server/working-state/service.test.ts +253 -0
- package/src/lib/server/working-state/service.ts +293 -0
- package/src/lib/validation/schemas.ts +1 -0
- package/src/lib/ws-client.ts +3 -3
- package/src/stores/slices/task-slice.ts +1 -4
- package/src/stores/use-chatroom-store.ts +2 -2
- package/src/types/index.ts +277 -12
|
@@ -49,6 +49,8 @@ import { logExecution } from '@/lib/server/execution-log'
|
|
|
49
49
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
50
50
|
import { getEnabledCapabilityIds, splitCapabilityIds } from '@/lib/capability-selection'
|
|
51
51
|
import { getSession, loadSessions, saveSession } from '@/lib/server/sessions/session-repository'
|
|
52
|
+
import { ensureRunContext } from '@/lib/server/run-context'
|
|
53
|
+
import { buildExecutionBrief, serializeExecutionBriefForDelegation } from '@/lib/server/execution-brief'
|
|
52
54
|
|
|
53
55
|
// ---------------------------------------------------------------------------
|
|
54
56
|
// Types
|
|
@@ -277,6 +279,16 @@ async function spawnSubagentImpl(
|
|
|
277
279
|
browserProfileId,
|
|
278
280
|
}
|
|
279
281
|
sessions[sid] = applyResolvedRoute(nextSession, resolvePrimaryAgentRoute(agent))
|
|
282
|
+
|
|
283
|
+
// Enrich child session with parent's RunContext for delegation handoff
|
|
284
|
+
const delegationContext = parent ? serializeExecutionBriefForDelegation(buildExecutionBrief({ sessionId: context.sessionId })) : null
|
|
285
|
+
if (delegationContext) {
|
|
286
|
+
const childCtx = ensureRunContext(null)
|
|
287
|
+
childCtx.parentContext = delegationContext
|
|
288
|
+
childCtx.objective = input.message.slice(0, 900)
|
|
289
|
+
sessions[sid].runContext = childCtx
|
|
290
|
+
}
|
|
291
|
+
|
|
280
292
|
saveSession(sid, sessions[sid])
|
|
281
293
|
|
|
282
294
|
log.info('subagent', 'Spawning', { agentId: agent.id, agentName: agent.name, depth: depth + 1, jobId: job.id, sessionId: sid })
|
|
@@ -228,7 +228,26 @@ describe('supervisor-reflection', () => {
|
|
|
228
228
|
model: 'gpt-test',
|
|
229
229
|
claudeSessionId: null,
|
|
230
230
|
messages: [
|
|
231
|
-
{
|
|
231
|
+
{
|
|
232
|
+
role: 'user',
|
|
233
|
+
text: 'I am moving to Lisbon next month and prefer short check-ins while I am juggling the move.',
|
|
234
|
+
time: 1,
|
|
235
|
+
semantics: {
|
|
236
|
+
taskIntent: 'general',
|
|
237
|
+
workType: 'general',
|
|
238
|
+
walletIntent: 'none',
|
|
239
|
+
isDeliverableTask: false,
|
|
240
|
+
isBroadGoal: false,
|
|
241
|
+
isResearchSynthesis: false,
|
|
242
|
+
hasHumanSignals: true,
|
|
243
|
+
hasSignificantEvent: true,
|
|
244
|
+
wantsScreenshots: false,
|
|
245
|
+
wantsOutboundDelivery: false,
|
|
246
|
+
wantsVoiceDelivery: false,
|
|
247
|
+
explicitToolRequests: [],
|
|
248
|
+
confidence: 0.98,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
232
251
|
{ role: 'assistant', text: 'Understood. I will keep updates tight and remember the move timing.', time: 2 },
|
|
233
252
|
],
|
|
234
253
|
createdAt: 1,
|
|
@@ -33,14 +33,16 @@ import { log } from '@/lib/server/logger'
|
|
|
33
33
|
import { logExecution } from '@/lib/server/execution-log'
|
|
34
34
|
import { logActivity } from '@/lib/server/storage'
|
|
35
35
|
import { createNotification } from '@/lib/server/create-notification'
|
|
36
|
+
import { foldReflectionIntoRunContext } from '@/lib/server/run-context'
|
|
37
|
+
import { getSession, saveSession } from '@/lib/server/sessions/session-repository'
|
|
38
|
+
import { cleanText } from '@/lib/server/text-normalization'
|
|
39
|
+
import { getMessages, getMessageCount, getRecentMessages } from '@/lib/server/messages/message-repository'
|
|
36
40
|
|
|
37
41
|
const TAG = 'supervisor-reflection'
|
|
38
42
|
|
|
39
43
|
const MAIN_LOOP_META_LINE_RE = /\[(?:MAIN_LOOP_META|MAIN_LOOP_PLAN|MAIN_LOOP_REVIEW|AGENT_HEARTBEAT_META)\]\s*(\{[^\n]*\})?/i
|
|
40
44
|
const DEFAULT_TRANSCRIPT_MESSAGES = 12
|
|
41
45
|
const DEFAULT_SNIPPET_CHARS = 800
|
|
42
|
-
const HUMAN_SIGNAL_RE = /\b(?:prefer|please|call me|don't call me|do not call me|i like|i dislike|i hate|i love|my pronouns|my partner|my wife|my husband|my kid|my child|my mom|my dad|my sister|my brother|birthday|anniversary|wedding|married|divorc|pregnan|baby|moved|moving|relocat|promotion|promoted|laid off|new job|job change|graduat|hospital|sick|illness|diagnos|passed away|funeral|grief|bereave|deadline|launch|fundraising|closing|house|home|travel)\b/i
|
|
43
|
-
const SIGNIFICANT_EVENT_RE = /\b(?:birthday|anniversary|wedding|married|divorc|pregnan|baby|moved|moving|relocat|promotion|promoted|laid off|new job|job change|graduat|hospital|sick|illness|diagnos|passed away|funeral|grief|bereave|deadline|launch|fundraising|closing|house|home|travel)\b/i
|
|
44
46
|
|
|
45
47
|
export interface SupervisorStateSnapshot {
|
|
46
48
|
followupChainCount?: number | null
|
|
@@ -81,13 +83,6 @@ function now(): number {
|
|
|
81
83
|
return Date.now()
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
function cleanText(value: unknown, max = 320): string | null {
|
|
85
|
-
if (typeof value !== 'string') return null
|
|
86
|
-
const compact = value.replace(/\s+/g, ' ').trim()
|
|
87
|
-
if (!compact) return null
|
|
88
|
-
return compact.slice(0, max)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
86
|
function looksLikeHtmlErrorPayload(value: string): boolean {
|
|
92
87
|
const normalized = value.toLowerCase()
|
|
93
88
|
let matches = 0
|
|
@@ -189,9 +184,11 @@ function buildIncident(
|
|
|
189
184
|
}
|
|
190
185
|
|
|
191
186
|
function sessionContextPressure(session: Session | null): boolean {
|
|
192
|
-
if (!session
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
if (!session) return false
|
|
188
|
+
const msgCount = getMessageCount(session.id)
|
|
189
|
+
if (msgCount >= 60) return true
|
|
190
|
+
const messages = getMessages(session.id)
|
|
191
|
+
const totalChars = messages.reduce((sum, message) => sum + String(message?.text || '').length, 0)
|
|
195
192
|
return totalChars >= 18_000
|
|
196
193
|
}
|
|
197
194
|
|
|
@@ -428,7 +425,7 @@ export async function executeSupervisorAutoActions(params: {
|
|
|
428
425
|
}
|
|
429
426
|
|
|
430
427
|
function buildSessionTranscript(session: Session, maxMessages = DEFAULT_TRANSCRIPT_MESSAGES): string {
|
|
431
|
-
const messages =
|
|
428
|
+
const messages = getRecentMessages(session.id, maxMessages)
|
|
432
429
|
const lines: string[] = []
|
|
433
430
|
for (const message of messages) {
|
|
434
431
|
if (!message || message.suppressed) continue
|
|
@@ -543,10 +540,21 @@ function normalizeNoteArray(value: unknown, limit = 4): string[] {
|
|
|
543
540
|
return out
|
|
544
541
|
}
|
|
545
542
|
|
|
543
|
+
function transcriptHasSemanticSignal(
|
|
544
|
+
session: Session | null,
|
|
545
|
+
signal: 'hasHumanSignals' | 'hasSignificantEvent',
|
|
546
|
+
): boolean {
|
|
547
|
+
if (!session) return false
|
|
548
|
+
const recentMessages = getRecentMessages(session.id, 8)
|
|
549
|
+
return recentMessages.some((message) => message?.role === 'user' && message?.semantics?.[signal] === true)
|
|
550
|
+
}
|
|
551
|
+
|
|
546
552
|
function transcriptHasHumanSignals(session: Session | null): boolean {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
553
|
+
return transcriptHasSemanticSignal(session, 'hasHumanSignals')
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function transcriptHasSignificantEvents(session: Session | null): boolean {
|
|
557
|
+
return transcriptHasSemanticSignal(session, 'hasSignificantEvent')
|
|
550
558
|
}
|
|
551
559
|
|
|
552
560
|
function parseReflectionResponse(raw: string): {
|
|
@@ -658,10 +666,11 @@ function shouldReflectRun(params: {
|
|
|
658
666
|
if (!surface || !runtimeScopeIncludes(params.runtimeScope, surface)) return false
|
|
659
667
|
if (params.status === 'cancelled') return false
|
|
660
668
|
if (surface === 'task') return Boolean(params.resultText.trim() || params.incidents.length > 0)
|
|
661
|
-
const meaningfulMessages =
|
|
662
|
-
? params.session.
|
|
669
|
+
const meaningfulMessages = params.session
|
|
670
|
+
? getMessages(params.session.id).filter((message) => message && !message.suppressed && (message.text || message.toolEvents?.length)).length
|
|
663
671
|
: 0
|
|
664
672
|
if (transcriptHasHumanSignals(params.session)) return true
|
|
673
|
+
if (transcriptHasSignificantEvents(params.session)) return true
|
|
665
674
|
if (params.incidents.length > 0) return true
|
|
666
675
|
if (params.toolEvents.length > 0) return true
|
|
667
676
|
if (params.resultText.trim().length >= 180) return true
|
|
@@ -788,7 +797,7 @@ function writeReflectionMemories(params: {
|
|
|
788
797
|
}
|
|
789
798
|
if (group.kind === 'significant_event') {
|
|
790
799
|
metadata.memoryFacet = 'event'
|
|
791
|
-
metadata.eventSalience =
|
|
800
|
+
metadata.eventSalience = 'high'
|
|
792
801
|
}
|
|
793
802
|
if (group.kind === 'open_loop') {
|
|
794
803
|
metadata.memoryFacet = 'followup'
|
|
@@ -1095,6 +1104,17 @@ export async function observeAutonomyRunOutcome(
|
|
|
1095
1104
|
reflections[reflection.id] = reflection
|
|
1096
1105
|
saveRunReflections(reflections)
|
|
1097
1106
|
|
|
1107
|
+
// Fold reflection notes into session RunContext (non-critical)
|
|
1108
|
+
try {
|
|
1109
|
+
const freshSession = getSession(input.sessionId) as Session | undefined
|
|
1110
|
+
if (freshSession) {
|
|
1111
|
+
freshSession.runContext = foldReflectionIntoRunContext(freshSession.runContext, reflection)
|
|
1112
|
+
saveSession(input.sessionId, freshSession)
|
|
1113
|
+
}
|
|
1114
|
+
} catch (err: unknown) {
|
|
1115
|
+
log.warn(TAG, 'RunContext reflection folding failed:', err instanceof Error ? err.message : String(err))
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1098
1118
|
// Quality degradation alert — if recent quality trend drops below 0.5
|
|
1099
1119
|
if (typeof reflection.qualityScore === 'number' && input.agentId) {
|
|
1100
1120
|
checkQualityDegradation(input.agentId).catch(() => {})
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { ChatAnthropic } from '@langchain/anthropic'
|
|
2
2
|
import { ChatOpenAI } from '@langchain/openai'
|
|
3
|
-
import { loadCredentials, decryptKey, loadAgents, loadSessions } from './storage'
|
|
4
3
|
import { getProviderList } from '../providers'
|
|
5
4
|
import { normalizeOpenClawEndpoint } from '@/lib/openclaw/openclaw-endpoint'
|
|
6
5
|
import { NON_LANGGRAPH_PROVIDER_IDS } from '../provider-sets'
|
|
7
6
|
import { resolveOllamaRuntimeConfig } from './ollama-runtime'
|
|
8
7
|
import { resolveProviderApiEndpoint, resolveProviderCredentialId } from './provider-endpoint'
|
|
8
|
+
import { getAgent } from './agents/agent-repository'
|
|
9
|
+
import { resolveCredentialSecret } from './credentials/credential-service'
|
|
10
|
+
import { getSession } from './sessions/session-repository'
|
|
9
11
|
import type { Agent } from '@/types'
|
|
10
12
|
|
|
11
13
|
const OLLAMA_CLOUD_URL = 'https://ollama.com/v1'
|
|
@@ -135,15 +137,7 @@ export function buildChatModel(opts: {
|
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
function resolveApiKeyFromCredential(credentialId: string | null | undefined): string | null {
|
|
138
|
-
|
|
139
|
-
const creds = loadCredentials()
|
|
140
|
-
const cred = creds[credentialId]
|
|
141
|
-
if (!cred?.encryptedKey) return null
|
|
142
|
-
try {
|
|
143
|
-
return decryptKey(cred.encryptedKey)
|
|
144
|
-
} catch {
|
|
145
|
-
return null
|
|
146
|
-
}
|
|
140
|
+
return resolveCredentialSecret(credentialId)
|
|
147
141
|
}
|
|
148
142
|
|
|
149
143
|
function normalizePreferenceValue(value: string | null | undefined): string {
|
|
@@ -222,12 +216,10 @@ export function resolveGenerationModelConfig(options?: {
|
|
|
222
216
|
excludeProviders?: string[]
|
|
223
217
|
}): ResolvedGenerationModelConfig {
|
|
224
218
|
const providers = getProviderList()
|
|
225
|
-
const agents = loadAgents()
|
|
226
|
-
const sessions = loadSessions()
|
|
227
219
|
const excludeProviders = new Set((options?.excludeProviders || []).map((value) => normalizePreferenceValue(value)).filter(Boolean))
|
|
228
|
-
const session = options?.sessionId ?
|
|
229
|
-
const sessionAgent = session?.agentId ?
|
|
230
|
-
const directAgent = options?.agentId ?
|
|
220
|
+
const session = options?.sessionId ? getSession(options.sessionId) : null
|
|
221
|
+
const sessionAgent = session?.agentId ? getAgent(session.agentId) as Agent | null : null
|
|
222
|
+
const directAgent = options?.agentId ? getAgent(options.agentId) as Agent | null : null
|
|
231
223
|
const resolved = resolvePreferredGenerationConfig(providers, [
|
|
232
224
|
...(Array.isArray(options?.preferred) ? options?.preferred : options?.preferred ? [options.preferred] : []),
|
|
233
225
|
...(session ? [{
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import assert from 'node:assert/strict'
|
|
2
2
|
import { test } from 'node:test'
|
|
3
3
|
import { routeTaskIntent } from './capability-router'
|
|
4
|
+
import type { MessageClassification } from '@/lib/server/chat-execution/message-classifier'
|
|
4
5
|
|
|
5
6
|
test('routeTaskIntent keeps recall-style prompts as general intent', () => {
|
|
6
7
|
const decision = routeTaskIntent(
|
|
7
8
|
'What token did we store earlier as e2e_validation_token? Reply only with the token.',
|
|
8
9
|
['memory', 'web_search'],
|
|
9
10
|
null,
|
|
11
|
+
makeClassification({ taskIntent: 'general' }),
|
|
10
12
|
)
|
|
11
13
|
assert.equal(decision.intent, 'general')
|
|
12
14
|
})
|
|
@@ -16,6 +18,7 @@ test('routeTaskIntent keeps coding prompts prioritized over memory keywords', ()
|
|
|
16
18
|
'Build and test a calculator app, then remember the final path in memory.',
|
|
17
19
|
['memory', 'shell', 'files'],
|
|
18
20
|
null,
|
|
21
|
+
makeClassification({ taskIntent: 'coding', workType: 'coding' }),
|
|
19
22
|
)
|
|
20
23
|
assert.equal(decision.intent, 'coding')
|
|
21
24
|
})
|
|
@@ -25,6 +28,14 @@ test('routeTaskIntent keeps hybrid research-plus-media prompts in research inten
|
|
|
25
28
|
'Can you tell me more if there is any news related to the US-Iran war, and can you send me some screenshots and give me a summary and maybe send me a voice note about it?',
|
|
26
29
|
['web_search', 'web_fetch', 'browser', 'manage_connectors'],
|
|
27
30
|
null,
|
|
31
|
+
makeClassification({
|
|
32
|
+
taskIntent: 'research',
|
|
33
|
+
workType: 'research',
|
|
34
|
+
wantsScreenshots: true,
|
|
35
|
+
wantsVoiceDelivery: true,
|
|
36
|
+
wantsOutboundDelivery: true,
|
|
37
|
+
isResearchSynthesis: true,
|
|
38
|
+
}),
|
|
28
39
|
)
|
|
29
40
|
|
|
30
41
|
assert.equal(decision.intent, 'research')
|
|
@@ -36,6 +47,12 @@ test('routeTaskIntent treats direct voice-note delivery as outreach', () => {
|
|
|
36
47
|
'Send me a voice note over WhatsApp summarizing what changed.',
|
|
37
48
|
['manage_connectors'],
|
|
38
49
|
null,
|
|
50
|
+
makeClassification({
|
|
51
|
+
taskIntent: 'outreach',
|
|
52
|
+
workType: 'writing',
|
|
53
|
+
wantsVoiceDelivery: true,
|
|
54
|
+
wantsOutboundDelivery: true,
|
|
55
|
+
}),
|
|
39
56
|
)
|
|
40
57
|
|
|
41
58
|
assert.equal(decision.intent, 'outreach')
|
|
@@ -45,10 +62,62 @@ test('routeTaskIntent treats direct voice-note delivery as outreach', () => {
|
|
|
45
62
|
test('routeTaskIntent treats keep-watching update requests as research even without explicit news keywords', () => {
|
|
46
63
|
const decision = routeTaskIntent(
|
|
47
64
|
'Tell me about the Iran war, keep watching for meaningful updates, and avoid duplicate reminders.',
|
|
48
|
-
['web_search', 'manage_schedules'],
|
|
65
|
+
['web_search', 'web_fetch', 'manage_schedules'],
|
|
49
66
|
null,
|
|
67
|
+
makeClassification({
|
|
68
|
+
taskIntent: 'research',
|
|
69
|
+
workType: 'research',
|
|
70
|
+
isResearchSynthesis: true,
|
|
71
|
+
}),
|
|
50
72
|
)
|
|
51
73
|
|
|
52
74
|
assert.equal(decision.intent, 'research')
|
|
53
75
|
assert.deepEqual(decision.preferredTools, ['web_search', 'web_fetch'])
|
|
54
76
|
})
|
|
77
|
+
|
|
78
|
+
test('routeTaskIntent uses structured classification when available', () => {
|
|
79
|
+
const classification: MessageClassification = {
|
|
80
|
+
taskIntent: 'browsing',
|
|
81
|
+
isDeliverableTask: true,
|
|
82
|
+
isBroadGoal: false,
|
|
83
|
+
walletIntent: 'none',
|
|
84
|
+
hasHumanSignals: false,
|
|
85
|
+
hasSignificantEvent: false,
|
|
86
|
+
isResearchSynthesis: true,
|
|
87
|
+
workType: 'research',
|
|
88
|
+
wantsScreenshots: true,
|
|
89
|
+
wantsOutboundDelivery: false,
|
|
90
|
+
wantsVoiceDelivery: false,
|
|
91
|
+
explicitToolRequests: ['browser'],
|
|
92
|
+
confidence: 0.92,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const decision = routeTaskIntent(
|
|
96
|
+
'Review this story and show me screenshots.',
|
|
97
|
+
['web_search', 'web_fetch', 'browser'],
|
|
98
|
+
null,
|
|
99
|
+
classification,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
assert.equal(decision.intent, 'browsing')
|
|
103
|
+
assert.deepEqual(decision.preferredTools, ['browser', 'web_fetch'])
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
function makeClassification(overrides: Partial<MessageClassification>): MessageClassification {
|
|
107
|
+
return {
|
|
108
|
+
taskIntent: 'general',
|
|
109
|
+
isDeliverableTask: false,
|
|
110
|
+
isBroadGoal: false,
|
|
111
|
+
walletIntent: 'none',
|
|
112
|
+
hasHumanSignals: false,
|
|
113
|
+
hasSignificantEvent: false,
|
|
114
|
+
isResearchSynthesis: false,
|
|
115
|
+
workType: 'general',
|
|
116
|
+
wantsScreenshots: false,
|
|
117
|
+
wantsOutboundDelivery: false,
|
|
118
|
+
wantsVoiceDelivery: false,
|
|
119
|
+
explicitToolRequests: [],
|
|
120
|
+
confidence: 0.9,
|
|
121
|
+
...overrides,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AppSettings } from '@/types'
|
|
2
2
|
import { dedup } from '@/lib/shared-utils'
|
|
3
|
-
import { getToolsForCapability,
|
|
3
|
+
import { getToolsForCapability, TOOL_CAPABILITY } from './tool-planning'
|
|
4
|
+
import type { MessageClassification } from '@/lib/server/chat-execution/message-classifier'
|
|
4
5
|
|
|
5
6
|
export type TaskIntent =
|
|
6
7
|
| 'coding'
|
|
@@ -25,38 +26,10 @@ function findFirstUrl(text: string): string | undefined {
|
|
|
25
26
|
return m?.[0]
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
function containsAny(text: string, terms: string[]): boolean {
|
|
29
|
-
return terms.some((term) => text.includes(term))
|
|
30
|
-
}
|
|
31
|
-
|
|
32
29
|
function dedupe(values: string[]): string[] {
|
|
33
30
|
return dedup(values.filter(Boolean))
|
|
34
31
|
}
|
|
35
32
|
|
|
36
|
-
function isMonitoringOrCurrentEventsRequest(text: string): boolean {
|
|
37
|
-
const normalized = text.toLowerCase()
|
|
38
|
-
if (!normalized.trim()) return false
|
|
39
|
-
return containsAny(normalized, [
|
|
40
|
-
'latest',
|
|
41
|
-
'news',
|
|
42
|
-
'headline',
|
|
43
|
-
'current event',
|
|
44
|
-
'recent update',
|
|
45
|
-
'recent updates',
|
|
46
|
-
'update me',
|
|
47
|
-
'updates',
|
|
48
|
-
'breaking',
|
|
49
|
-
'developments',
|
|
50
|
-
'keep watching',
|
|
51
|
-
'watch for',
|
|
52
|
-
'watching for',
|
|
53
|
-
'monitor',
|
|
54
|
-
'track',
|
|
55
|
-
'follow the situation',
|
|
56
|
-
'tell me if anything changes',
|
|
57
|
-
])
|
|
58
|
-
}
|
|
59
|
-
|
|
60
33
|
function preferredToolsForCapabilities(enabledExtensions: string[], capabilities: string[], fallback: string[] = []): string[] {
|
|
61
34
|
const preferred = capabilities.flatMap((capability) => getToolsForCapability(enabledExtensions, capability))
|
|
62
35
|
return dedupe(preferred.length > 0 ? preferred : fallback)
|
|
@@ -90,68 +63,36 @@ export function routeTaskIntent(
|
|
|
90
63
|
message: string,
|
|
91
64
|
enabledExtensions: string[],
|
|
92
65
|
settings?: AppSettings | null,
|
|
66
|
+
classification?: MessageClassification | null,
|
|
93
67
|
): CapabilityRoutingDecision {
|
|
94
|
-
const text = (message || '').toLowerCase()
|
|
95
68
|
const url = findFirstUrl(message || '')
|
|
96
69
|
const delegateOrder = normalizeDelegateOrder(settings?.autonomyPreferredDelegates)
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
const researchLike = matchedCapabilities.has(TOOL_CAPABILITY.researchSearch)
|
|
103
|
-
|| matchedCapabilities.has(TOOL_CAPABILITY.researchFetch)
|
|
104
|
-
|| isMonitoringOrCurrentEventsRequest(text)
|
|
105
|
-
|| !!url
|
|
70
|
+
const intent = classification?.taskIntent || 'general'
|
|
71
|
+
const confidence = classification?.confidence ?? 0
|
|
72
|
+
const wantsVoiceDelivery = classification?.wantsVoiceDelivery === true
|
|
73
|
+
const wantsScreenshots = classification?.wantsScreenshots === true
|
|
74
|
+
const wantsOutboundDelivery = classification?.wantsOutboundDelivery === true
|
|
106
75
|
|
|
107
|
-
|
|
108
|
-
'build',
|
|
109
|
-
'implement',
|
|
110
|
-
'create app',
|
|
111
|
-
'refactor',
|
|
112
|
-
'fix bug',
|
|
113
|
-
'write code',
|
|
114
|
-
'codebase',
|
|
115
|
-
'typescript',
|
|
116
|
-
'javascript',
|
|
117
|
-
'react',
|
|
118
|
-
'next.js',
|
|
119
|
-
'unit test',
|
|
120
|
-
'run tests',
|
|
121
|
-
'compile',
|
|
122
|
-
'npm ',
|
|
123
|
-
'pnpm ',
|
|
124
|
-
'yarn ',
|
|
125
|
-
])
|
|
126
|
-
if (coding) {
|
|
76
|
+
if (intent === 'coding') {
|
|
127
77
|
return {
|
|
128
78
|
intent: 'coding',
|
|
129
|
-
confidence
|
|
79
|
+
confidence,
|
|
130
80
|
preferredTools: ['claude_code', 'codex_cli', 'opencode_cli', 'shell', 'files', 'edit_file'],
|
|
131
81
|
preferredDelegates: delegateOrder,
|
|
132
82
|
primaryUrl: url,
|
|
133
83
|
}
|
|
134
84
|
}
|
|
135
85
|
|
|
136
|
-
|
|
137
|
-
'send update',
|
|
138
|
-
'message',
|
|
139
|
-
'whatsapp',
|
|
140
|
-
'telegram',
|
|
141
|
-
'slack',
|
|
142
|
-
'discord',
|
|
143
|
-
'notify',
|
|
144
|
-
'broadcast',
|
|
145
|
-
]) || (!researchLike && (wantsVoiceNote || wantsMediaDelivery || wantsChannelDelivery))
|
|
146
|
-
if (outreach) {
|
|
86
|
+
if (intent === 'outreach') {
|
|
147
87
|
return {
|
|
148
88
|
intent: 'outreach',
|
|
149
|
-
confidence
|
|
89
|
+
confidence,
|
|
150
90
|
preferredTools: preferredToolsForCapabilities(
|
|
151
91
|
enabledExtensions,
|
|
152
92
|
[
|
|
153
|
-
TOOL_CAPABILITY.deliveryVoiceNote,
|
|
154
|
-
TOOL_CAPABILITY.deliveryMedia,
|
|
93
|
+
...(wantsVoiceDelivery ? [TOOL_CAPABILITY.deliveryVoiceNote] : []),
|
|
94
|
+
...(wantsScreenshots ? [TOOL_CAPABILITY.deliveryMedia] : []),
|
|
95
|
+
...(wantsOutboundDelivery || wantsVoiceDelivery ? [TOOL_CAPABILITY.deliveryMessage] : []),
|
|
155
96
|
TOOL_CAPABILITY.deliveryMessage,
|
|
156
97
|
],
|
|
157
98
|
['connector_message_tool', 'manage_connectors', 'manage_sessions'],
|
|
@@ -161,35 +102,20 @@ export function routeTaskIntent(
|
|
|
161
102
|
}
|
|
162
103
|
}
|
|
163
104
|
|
|
164
|
-
|
|
165
|
-
'schedule',
|
|
166
|
-
'every day',
|
|
167
|
-
'every week',
|
|
168
|
-
'cron',
|
|
169
|
-
'recurring',
|
|
170
|
-
'remind',
|
|
171
|
-
'follow up tomorrow',
|
|
172
|
-
]) && !researchLike
|
|
173
|
-
if (scheduling) {
|
|
105
|
+
if (intent === 'scheduling') {
|
|
174
106
|
return {
|
|
175
107
|
intent: 'scheduling',
|
|
176
|
-
confidence
|
|
108
|
+
confidence,
|
|
177
109
|
preferredTools: ['manage_schedules', 'manage_tasks'],
|
|
178
110
|
preferredDelegates: delegateOrder,
|
|
179
111
|
primaryUrl: url,
|
|
180
112
|
}
|
|
181
113
|
}
|
|
182
114
|
|
|
183
|
-
|
|
184
|
-
matchedCapabilities.has(TOOL_CAPABILITY.browserNavigate)
|
|
185
|
-
|| matchedCapabilities.has(TOOL_CAPABILITY.browserCapture)
|
|
186
|
-
|| getToolsForCapability(enabledExtensions, TOOL_CAPABILITY.browserNavigate).length > 0
|
|
187
|
-
|| getToolsForCapability(enabledExtensions, TOOL_CAPABILITY.browserCapture).length > 0
|
|
188
|
-
)
|
|
189
|
-
if (browsing) {
|
|
115
|
+
if (intent === 'browsing') {
|
|
190
116
|
return {
|
|
191
117
|
intent: 'browsing',
|
|
192
|
-
confidence
|
|
118
|
+
confidence,
|
|
193
119
|
preferredTools: preferredToolsForCapabilities(
|
|
194
120
|
enabledExtensions,
|
|
195
121
|
[
|
|
@@ -204,22 +130,21 @@ export function routeTaskIntent(
|
|
|
204
130
|
}
|
|
205
131
|
}
|
|
206
132
|
|
|
207
|
-
|
|
208
|
-
if (research) {
|
|
133
|
+
if (intent === 'research') {
|
|
209
134
|
const preferred = preferredToolsForCapabilities(
|
|
210
135
|
enabledExtensions,
|
|
211
136
|
[
|
|
212
137
|
TOOL_CAPABILITY.researchSearch,
|
|
213
138
|
TOOL_CAPABILITY.researchFetch,
|
|
214
139
|
...(wantsScreenshots ? [TOOL_CAPABILITY.browserCapture] : []),
|
|
215
|
-
...(
|
|
216
|
-
...(
|
|
140
|
+
...(wantsVoiceDelivery ? [TOOL_CAPABILITY.deliveryVoiceNote] : []),
|
|
141
|
+
...(wantsOutboundDelivery ? [TOOL_CAPABILITY.deliveryMedia, TOOL_CAPABILITY.deliveryMessage] : []),
|
|
217
142
|
],
|
|
218
143
|
['web_search', 'web_fetch', 'browser'],
|
|
219
144
|
)
|
|
220
145
|
return {
|
|
221
146
|
intent: 'research',
|
|
222
|
-
confidence
|
|
147
|
+
confidence,
|
|
223
148
|
preferredTools: preferred,
|
|
224
149
|
preferredDelegates: delegateOrder,
|
|
225
150
|
primaryUrl: url,
|
|
@@ -228,7 +153,7 @@ export function routeTaskIntent(
|
|
|
228
153
|
|
|
229
154
|
return {
|
|
230
155
|
intent: 'general',
|
|
231
|
-
confidence
|
|
156
|
+
confidence,
|
|
232
157
|
preferredTools: [],
|
|
233
158
|
preferredDelegates: delegateOrder,
|
|
234
159
|
primaryUrl: url,
|
|
@@ -398,21 +398,6 @@ export function findFirstUrl(text: string): string | null {
|
|
|
398
398
|
return match?.[0] || null
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
-
export function isMemoryListIntent(message: string): boolean {
|
|
402
|
-
const text = message.toLowerCase()
|
|
403
|
-
if (!/\bmemory|memories|remember\b/.test(text)) return false
|
|
404
|
-
if (/\b(save|store|memorize|add to memory|write to memory|remember this)\b/.test(text)) return false
|
|
405
|
-
if (/\bmemory_tool\b/.test(text)) return true
|
|
406
|
-
return (
|
|
407
|
-
/\blist\b[\s\w]{0,24}\bmemories\b/.test(text)
|
|
408
|
-
|| /\bshow\b[\s\w]{0,24}\bmemories\b/.test(text)
|
|
409
|
-
|| /\bget\b[\s\w]{0,24}\bmemories\b/.test(text)
|
|
410
|
-
|| /\bwhat\b[\s\w]{0,40}\bmemories\b/.test(text)
|
|
411
|
-
|| /\bwhat do you remember\b/.test(text)
|
|
412
|
-
|| /\brecall\b[\s\w]{0,24}\bmemories?\b/.test(text)
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
401
|
export function extractDelegationTask(message: string, toolName: string): string | null {
|
|
417
402
|
if (!message.toLowerCase().includes(toolName.toLowerCase())) return null
|
|
418
403
|
const patterns = [
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { MessageToolEvent } from '@/types'
|
|
2
2
|
import { canonicalizeExtensionId } from '@/lib/server/tool-aliases'
|
|
3
3
|
import { extractSuggestions } from '@/lib/server/suggestions'
|
|
4
|
-
import {
|
|
5
|
-
looksLikeExternalWalletTask,
|
|
6
|
-
} from '@/lib/server/chat-execution/stream-continuation'
|
|
7
4
|
import type { MessageClassification } from '@/lib/server/chat-execution/message-classifier'
|
|
8
5
|
import {
|
|
9
6
|
buildSuccessfulMemoryMutationResponse,
|
|
@@ -82,7 +79,8 @@ export function shouldForceExternalServiceSummary(params: {
|
|
|
82
79
|
toolEventCount: number
|
|
83
80
|
classification?: MessageClassification | null
|
|
84
81
|
}): boolean {
|
|
85
|
-
const walletDetected = params.classification
|
|
82
|
+
const walletDetected = params.classification?.walletIntent !== undefined
|
|
83
|
+
&& params.classification.walletIntent !== 'none'
|
|
86
84
|
if (!walletDetected) return false
|
|
87
85
|
if (!params.hasToolCalls || params.toolEventCount === 0) return false
|
|
88
86
|
const trimmed = params.finalResponse.trim()
|