@swarmclawai/swarmclaw 1.2.8 → 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 +30 -6
- package/package.json +2 -2
- 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/connectors/route.ts +2 -2
- 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/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-sheet.tsx +2 -40
- package/src/components/agents/inspector-panel.tsx +0 -83
- package/src/components/chat/chat-card.tsx +0 -31
- package/src/components/chat/message-bubble.tsx +1 -108
- package/src/components/connectors/connector-sheet.tsx +25 -1
- 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/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/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 +0 -2
- package/src/lib/server/capability-router.test.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
- package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
- 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 +2 -22
- package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
- package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
- package/src/lib/server/chat-execution/message-classifier.ts +1 -16
- package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
- package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
- 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 +8 -123
- package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
- 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/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/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/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/persistence/storage-context.ts +0 -5
- 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 +0 -9
- 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/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 +0 -1
- package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
- package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
- package/src/lib/server/session-tools/crud.ts +0 -14
- package/src/lib/server/session-tools/delegate.ts +0 -4
- package/src/lib/server/session-tools/index.ts +0 -4
- package/src/lib/server/session-tools/team-context.ts +0 -3
- package/src/lib/server/storage-normalization.ts +8 -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 +0 -1
- package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
- package/src/lib/server/tool-capability-policy.ts +0 -2
- package/src/lib/server/tool-planning.ts +0 -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/strip-internal-metadata.test.ts +1 -1
- package/src/lib/strip-internal-metadata.ts +1 -1
- package/src/lib/tool-definitions.ts +0 -1
- package/src/lib/validation/schemas.ts +33 -2
- package/src/stores/slices/data-slice.ts +5 -1
- package/src/stores/slices/ui-slice.ts +0 -4
- package/src/types/agent.ts +0 -84
- package/src/types/app-settings.ts +0 -2
- package/src/types/approval.ts +0 -2
- package/src/types/connector.ts +1 -0
- package/src/types/index.ts +1 -1
- package/src/types/message.ts +0 -1
- package/src/types/misc.ts +0 -2
- package/src/types/protocol.ts +0 -2
- package/src/types/run.ts +0 -3
- package/src/types/session.ts +1 -51
- package/src/types/swarmdock.ts +29 -0
- package/src/types/task.ts +7 -3
- package/src/types/working-state.ts +2 -9
- 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/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/types/mission.ts +0 -185
- package/src/views/settings/section-wallets.tsx +0 -35
|
@@ -34,80 +34,6 @@ function canonicalizeValue(value: unknown): unknown {
|
|
|
34
34
|
}, {})
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function canonicalizeEthereumTransaction(value: unknown): Record<string, unknown> | null {
|
|
38
|
-
if (!isPlainRecord(value)) return null
|
|
39
|
-
const tx = value
|
|
40
|
-
const comparable: Record<string, unknown> = {}
|
|
41
|
-
const to = trimString(tx.to)
|
|
42
|
-
const data = trimString(tx.data)
|
|
43
|
-
const valueAtomic = tx.value
|
|
44
|
-
const type = normalizeScalar(tx.type)
|
|
45
|
-
const chainId = normalizeScalar(tx.chainId)
|
|
46
|
-
|
|
47
|
-
if (to) comparable.to = /^0x[0-9a-f]+$/i.test(to) ? to.toLowerCase() : to
|
|
48
|
-
if (data) comparable.data = /^0x[0-9a-f]+$/i.test(data) ? data.toLowerCase() : data
|
|
49
|
-
if (valueAtomic !== undefined && valueAtomic !== null && valueAtomic !== '') comparable.value = normalizeScalar(valueAtomic)
|
|
50
|
-
if (type !== null && type !== undefined && type !== '') comparable.type = type
|
|
51
|
-
if (chainId !== null && chainId !== undefined && chainId !== '') comparable.chainId = chainId
|
|
52
|
-
|
|
53
|
-
return Object.keys(comparable).length > 0 ? comparable : null
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function comparableWalletActionPayload(data: Record<string, unknown>): Record<string, unknown> {
|
|
57
|
-
const action = trimString(data.action)
|
|
58
|
-
const chain = trimString(data.chain)
|
|
59
|
-
const network = trimString(data.network)
|
|
60
|
-
const payload: Record<string, unknown> = {
|
|
61
|
-
action,
|
|
62
|
-
chain,
|
|
63
|
-
network,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const transaction = canonicalizeEthereumTransaction(data.transaction)
|
|
67
|
-
if (transaction) payload.transaction = transaction
|
|
68
|
-
|
|
69
|
-
const signedTransactionFingerprint = trimString(data.signedTransactionFingerprint)
|
|
70
|
-
if (signedTransactionFingerprint) payload.signedTransactionFingerprint = signedTransactionFingerprint
|
|
71
|
-
|
|
72
|
-
const transactionFingerprint = trimString(data.transactionFingerprint)
|
|
73
|
-
if (transactionFingerprint) payload.transactionFingerprint = transactionFingerprint
|
|
74
|
-
|
|
75
|
-
const messageDigest = trimString(data.messageDigest)
|
|
76
|
-
if (messageDigest) payload.messageDigest = messageDigest
|
|
77
|
-
|
|
78
|
-
const domain = canonicalizeValue(data.domain)
|
|
79
|
-
if (domain && typeof domain === 'object') payload.domain = domain
|
|
80
|
-
|
|
81
|
-
const types = canonicalizeValue(data.types)
|
|
82
|
-
if (types && typeof types === 'object') payload.types = types
|
|
83
|
-
|
|
84
|
-
const value = canonicalizeValue(data.value)
|
|
85
|
-
if (value && typeof value === 'object') payload.value = value
|
|
86
|
-
|
|
87
|
-
const toAddress = trimString(data.toAddress)
|
|
88
|
-
if (toAddress) payload.toAddress = /^0x[0-9a-f]+$/i.test(toAddress) ? toAddress.toLowerCase() : toAddress
|
|
89
|
-
|
|
90
|
-
const amountAtomic = normalizeScalar(data.amountAtomic)
|
|
91
|
-
if (amountAtomic !== null && amountAtomic !== undefined && amountAtomic !== '') payload.amountAtomic = amountAtomic
|
|
92
|
-
|
|
93
|
-
const sellToken = trimString(data.sellToken)
|
|
94
|
-
if (sellToken) payload.sellToken = /^0x[0-9a-f]+$/i.test(sellToken) ? sellToken.toLowerCase() : sellToken
|
|
95
|
-
|
|
96
|
-
const buyToken = trimString(data.buyToken)
|
|
97
|
-
if (buyToken) payload.buyToken = /^0x[0-9a-f]+$/i.test(buyToken) ? buyToken.toLowerCase() : buyToken
|
|
98
|
-
|
|
99
|
-
const recipient = trimString(data.recipient)
|
|
100
|
-
if (recipient) payload.recipient = /^0x[0-9a-f]+$/i.test(recipient) ? recipient.toLowerCase() : recipient
|
|
101
|
-
|
|
102
|
-
const routeProvider = trimString(data.routeProvider)
|
|
103
|
-
if (routeProvider) payload.routeProvider = routeProvider
|
|
104
|
-
|
|
105
|
-
const slippageBps = normalizeScalar(data.slippageBps)
|
|
106
|
-
if (slippageBps !== null && slippageBps !== undefined && slippageBps !== '') payload.slippageBps = slippageBps
|
|
107
|
-
|
|
108
|
-
return payload
|
|
109
|
-
}
|
|
110
|
-
|
|
111
37
|
export function buildApprovalComparablePayload(
|
|
112
38
|
category: ApprovalCategory,
|
|
113
39
|
data: Record<string, unknown>,
|
|
@@ -128,17 +54,6 @@ export function buildApprovalComparablePayload(
|
|
|
128
54
|
extensionId: trimString(data.extensionId),
|
|
129
55
|
filename: trimString(data.filename),
|
|
130
56
|
}
|
|
131
|
-
case 'wallet_transfer': {
|
|
132
|
-
const toAddress = trimString(data.toAddress)
|
|
133
|
-
return {
|
|
134
|
-
chain: trimString(data.chain),
|
|
135
|
-
toAddress: /^0x[0-9a-f]+$/i.test(toAddress) ? toAddress.toLowerCase() : toAddress,
|
|
136
|
-
amountAtomic: normalizeScalar(data.amountAtomic),
|
|
137
|
-
memo: trimString(data.memo),
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
case 'wallet_action':
|
|
141
|
-
return comparableWalletActionPayload(data)
|
|
142
57
|
case 'human_loop':
|
|
143
58
|
return {
|
|
144
59
|
question: trimString(data.question),
|
|
@@ -56,19 +56,19 @@ describe('approvals', () => {
|
|
|
56
56
|
title: 'Human approval',
|
|
57
57
|
data: { question: 'Proceed?' },
|
|
58
58
|
})
|
|
59
|
-
const
|
|
60
|
-
category: '
|
|
61
|
-
title: '
|
|
62
|
-
data: {
|
|
59
|
+
const other = approvals.requestApproval({
|
|
60
|
+
category: 'human_loop',
|
|
61
|
+
title: 'Another approval',
|
|
62
|
+
data: { question: 'Continue?' },
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
-
await approvals.submitDecision(
|
|
65
|
+
await approvals.submitDecision(other.id, true)
|
|
66
66
|
|
|
67
67
|
const pending = approvals.listPendingApprovals()
|
|
68
68
|
const humanPending = approvals.listPendingApprovals('human_loop')
|
|
69
69
|
|
|
70
70
|
assert.equal(pending.some((entry) => entry.id === human.id), true)
|
|
71
|
-
assert.equal(pending.some((entry) => entry.id ===
|
|
71
|
+
assert.equal(pending.some((entry) => entry.id === other.id), false)
|
|
72
72
|
assert.equal(humanPending.some((entry) => entry.id === human.id), true)
|
|
73
73
|
assert.equal(humanPending.every((entry) => entry.category === 'human_loop'), true)
|
|
74
74
|
})
|
|
@@ -5,7 +5,6 @@ import { notify } from './ws-hub'
|
|
|
5
5
|
import { dispatchWake } from '@/lib/server/runtime/wake-dispatcher'
|
|
6
6
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
7
7
|
import { enqueueSessionRun } from '@/lib/server/runtime/session-run-manager'
|
|
8
|
-
import { requestMissionTicksForApprovalDecision } from '@/lib/server/missions/mission-service'
|
|
9
8
|
|
|
10
9
|
function trimToString(value: unknown): string {
|
|
11
10
|
return typeof value === 'string' ? value.trim() : ''
|
|
@@ -122,11 +121,6 @@ async function persistApprovalDecision(request: ApprovalRequest, approved: boole
|
|
|
122
121
|
// best-effort trigger only
|
|
123
122
|
})
|
|
124
123
|
if (request.sessionId) notify(`session:${request.sessionId}`)
|
|
125
|
-
requestMissionTicksForApprovalDecision({
|
|
126
|
-
approvalId: request.id,
|
|
127
|
-
status: approved ? 'approved' : 'rejected',
|
|
128
|
-
sessionId: request.sessionId || null,
|
|
129
|
-
})
|
|
130
124
|
return request
|
|
131
125
|
}
|
|
132
126
|
|
|
@@ -7,10 +7,8 @@ import '@/lib/server/session-tools/memory'
|
|
|
7
7
|
import '@/lib/server/session-tools/platform'
|
|
8
8
|
import '@/lib/server/session-tools/monitor'
|
|
9
9
|
import '@/lib/server/session-tools/discovery'
|
|
10
|
-
import '@/lib/server/session-tools/wallet'
|
|
11
10
|
import '@/lib/server/session-tools/connector'
|
|
12
11
|
// http_request consolidated into web 'api' action
|
|
13
|
-
import '@/lib/server/session-tools/canvas'
|
|
14
12
|
import '@/lib/server/session-tools/chatroom'
|
|
15
13
|
import '@/lib/server/session-tools/delegate'
|
|
16
14
|
import '@/lib/server/session-tools/schedule'
|
|
@@ -80,7 +80,6 @@ test('routeTaskIntent uses structured classification when available', () => {
|
|
|
80
80
|
taskIntent: 'browsing',
|
|
81
81
|
isDeliverableTask: true,
|
|
82
82
|
isBroadGoal: false,
|
|
83
|
-
walletIntent: 'none',
|
|
84
83
|
hasHumanSignals: false,
|
|
85
84
|
hasSignificantEvent: false,
|
|
86
85
|
isResearchSynthesis: true,
|
|
@@ -108,7 +107,6 @@ function makeClassification(overrides: Partial<MessageClassification>): MessageC
|
|
|
108
107
|
taskIntent: 'general',
|
|
109
108
|
isDeliverableTask: false,
|
|
110
109
|
isBroadGoal: false,
|
|
111
|
-
walletIntent: 'none',
|
|
112
110
|
hasHumanSignals: false,
|
|
113
111
|
hasSignificantEvent: false,
|
|
114
112
|
isResearchSynthesis: false,
|
|
@@ -108,31 +108,31 @@ describe('collectToolEvent', () => {
|
|
|
108
108
|
const bag: MessageToolEvent[] = []
|
|
109
109
|
collectToolEvent({
|
|
110
110
|
t: 'tool_call',
|
|
111
|
-
toolName: '
|
|
112
|
-
toolInput: '{"
|
|
113
|
-
toolCallId: 'call-
|
|
111
|
+
toolName: 'http_request',
|
|
112
|
+
toolInput: '{"method":"GET","url":"https://api-a.example.com"}',
|
|
113
|
+
toolCallId: 'call-a',
|
|
114
114
|
}, bag)
|
|
115
115
|
collectToolEvent({
|
|
116
116
|
t: 'tool_call',
|
|
117
|
-
toolName: '
|
|
118
|
-
toolInput: '{"
|
|
119
|
-
toolCallId: 'call-
|
|
117
|
+
toolName: 'http_request',
|
|
118
|
+
toolInput: '{"method":"GET","url":"https://api-b.example.com"}',
|
|
119
|
+
toolCallId: 'call-b',
|
|
120
120
|
}, bag)
|
|
121
121
|
collectToolEvent({
|
|
122
122
|
t: 'tool_result',
|
|
123
|
-
toolName: '
|
|
124
|
-
toolOutput: '{"
|
|
125
|
-
toolCallId: 'call-
|
|
123
|
+
toolName: 'http_request',
|
|
124
|
+
toolOutput: '{"source":"api-a"}',
|
|
125
|
+
toolCallId: 'call-a',
|
|
126
126
|
}, bag)
|
|
127
127
|
collectToolEvent({
|
|
128
128
|
t: 'tool_result',
|
|
129
|
-
toolName: '
|
|
130
|
-
toolOutput: '{"
|
|
131
|
-
toolCallId: 'call-
|
|
129
|
+
toolName: 'http_request',
|
|
130
|
+
toolOutput: '{"source":"api-b"}',
|
|
131
|
+
toolCallId: 'call-b',
|
|
132
132
|
}, bag)
|
|
133
133
|
|
|
134
|
-
assert.equal(bag[0].output, '{"
|
|
135
|
-
assert.equal(bag[1].output, '{"
|
|
134
|
+
assert.equal(bag[0].output, '{"source":"api-a"}')
|
|
135
|
+
assert.equal(bag[1].output, '{"source":"api-b"}')
|
|
136
136
|
})
|
|
137
137
|
})
|
|
138
138
|
|
|
@@ -3,7 +3,6 @@ import type { MessageToolEvent, SSEEvent } from '@/types'
|
|
|
3
3
|
export interface ExecuteChatTurnInput {
|
|
4
4
|
sessionId: string
|
|
5
5
|
message: string
|
|
6
|
-
missionId?: string | null
|
|
7
6
|
imagePath?: string
|
|
8
7
|
imageUrl?: string
|
|
9
8
|
attachedFiles?: string[]
|
|
@@ -27,7 +26,6 @@ export interface ExecuteChatTurnInput {
|
|
|
27
26
|
export interface ExecuteChatTurnResult {
|
|
28
27
|
runId?: string
|
|
29
28
|
sessionId: string
|
|
30
|
-
missionId?: string | null
|
|
31
29
|
text: string
|
|
32
30
|
persisted: boolean
|
|
33
31
|
toolEvents: MessageToolEvent[]
|
|
@@ -321,7 +321,6 @@ export function requestedToolNamesFromMessage(message: string): string[] {
|
|
|
321
321
|
'memory_get',
|
|
322
322
|
'memory_store',
|
|
323
323
|
'memory_update',
|
|
324
|
-
'wallet_tool',
|
|
325
324
|
'http_request',
|
|
326
325
|
'send_file',
|
|
327
326
|
'schedule_wake',
|
|
@@ -339,7 +338,6 @@ export function requestedToolNamesFromMessage(message: string): string[] {
|
|
|
339
338
|
'execute',
|
|
340
339
|
'files',
|
|
341
340
|
'edit_file',
|
|
342
|
-
'canvas',
|
|
343
341
|
'mailbox',
|
|
344
342
|
'email',
|
|
345
343
|
]
|
|
@@ -72,22 +72,14 @@ export function getExplicitRequiredToolNames(userMessage: string, enabledExtensi
|
|
|
72
72
|
return required
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export function shouldForceExternalServiceSummary(
|
|
75
|
+
export function shouldForceExternalServiceSummary(_params: {
|
|
76
76
|
userMessage: string
|
|
77
77
|
finalResponse: string
|
|
78
78
|
hasToolCalls: boolean
|
|
79
79
|
toolEventCount: number
|
|
80
80
|
classification?: MessageClassification | null
|
|
81
81
|
}): boolean {
|
|
82
|
-
|
|
83
|
-
&& params.classification.walletIntent !== 'none'
|
|
84
|
-
if (!walletDetected) return false
|
|
85
|
-
if (!params.hasToolCalls || params.toolEventCount === 0) return false
|
|
86
|
-
const trimmed = params.finalResponse.trim()
|
|
87
|
-
if (!trimmed) return true
|
|
88
|
-
if (/\b(blocker|blocked|cannot|can't|requires|need|missing|last reversible step|next step)\b/i.test(trimmed)) return false
|
|
89
|
-
if (trimmed.length >= 240 && !/(let me|i'll|i will|checking|verify|promising|look into|explore|access their interface)/i.test(trimmed)) return false
|
|
90
|
-
return /:$/.test(trimmed) || /(let me|i'll|i will|checking|verify|promising|look into|explore|access their interface)/i.test(trimmed) || trimmed.length < 240
|
|
82
|
+
return false
|
|
91
83
|
}
|
|
92
84
|
|
|
93
85
|
export type TerminalToolBoundary =
|
|
@@ -146,26 +138,6 @@ export function resolveSuccessfulTerminalToolBoundary(params: {
|
|
|
146
138
|
return null
|
|
147
139
|
}
|
|
148
140
|
|
|
149
|
-
export function getWalletApprovalBoundaryAction(output: string): string | null {
|
|
150
|
-
if (!output.includes('extension_wallet_')) return null
|
|
151
|
-
if (/"type":"extension_wallet_transfer_request"/.test(output)) return 'send'
|
|
152
|
-
const actionMatch = output.match(/"action":"([^"]+)"/)
|
|
153
|
-
const action = actionMatch?.[1] || ''
|
|
154
|
-
if (!action) return null
|
|
155
|
-
const readOnlyActions = new Set([
|
|
156
|
-
'balance',
|
|
157
|
-
'address',
|
|
158
|
-
'transactions',
|
|
159
|
-
'encode_contract_call',
|
|
160
|
-
'simulate_transaction',
|
|
161
|
-
])
|
|
162
|
-
return readOnlyActions.has(action) ? null : action
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export function isWalletSimulationResult(toolName: string, output: string): boolean {
|
|
166
|
-
return toolName === 'wallet_tool' && /"status":"simulated"/.test(output)
|
|
167
|
-
}
|
|
168
|
-
|
|
169
141
|
export function updateStreamedToolEvents(
|
|
170
142
|
events: MessageToolEvent[],
|
|
171
143
|
event: { type: 'call' | 'result'; name: string; input?: string; output?: string; toolCallId?: string },
|
|
@@ -26,9 +26,6 @@ import { estimateCost } from '@/lib/server/cost'
|
|
|
26
26
|
import { refreshSessionIdentityState } from '@/lib/server/identity-continuity'
|
|
27
27
|
import { log } from '@/lib/server/logger'
|
|
28
28
|
import { syncSessionArchiveMemory } from '@/lib/server/memory/session-archive-memory'
|
|
29
|
-
import {
|
|
30
|
-
applyMissionOutcomeForTurn,
|
|
31
|
-
} from '@/lib/server/missions/mission-service'
|
|
32
29
|
import { runCapabilityHook, transformCapabilityText } from '@/lib/server/native-capabilities'
|
|
33
30
|
import { isHeartbeatSource } from '@/lib/server/runtime/heartbeat-source'
|
|
34
31
|
import { perf } from '@/lib/server/runtime/perf'
|
|
@@ -181,7 +178,6 @@ export async function finalizeChatTurn(params: {
|
|
|
181
178
|
sessionForRun,
|
|
182
179
|
appSettings,
|
|
183
180
|
lifecycleRunId,
|
|
184
|
-
mission,
|
|
185
181
|
extensionsForRun,
|
|
186
182
|
effectiveMessage,
|
|
187
183
|
providerType,
|
|
@@ -589,45 +585,15 @@ export async function finalizeChatTurn(params: {
|
|
|
589
585
|
}
|
|
590
586
|
|
|
591
587
|
refreshSessionIdentityState(current, currentAgent)
|
|
592
|
-
let resolvedMissionId = mission?.id || current.missionId || null
|
|
593
|
-
let updatedMission = mission || null
|
|
594
|
-
if (resolvedMissionId) {
|
|
595
|
-
updatedMission = await applyMissionOutcomeForTurn({
|
|
596
|
-
session: current,
|
|
597
|
-
missionId: resolvedMissionId,
|
|
598
|
-
source,
|
|
599
|
-
runId: lifecycleRunId,
|
|
600
|
-
message,
|
|
601
|
-
assistantText: hiddenControlOnly ? '' : textForPersistence,
|
|
602
|
-
error: errorMessage || null,
|
|
603
|
-
toolEvents: persistedToolEvents,
|
|
604
|
-
})
|
|
605
|
-
if (updatedMission?.id) {
|
|
606
|
-
resolvedMissionId = updatedMission.id
|
|
607
|
-
current.missionId = updatedMission.id
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
const missionStateChanged = Boolean(
|
|
611
|
-
updatedMission
|
|
612
|
-
&& (
|
|
613
|
-
updatedMission.id !== mission?.id
|
|
614
|
-
|| updatedMission.updatedAt !== mission?.updatedAt
|
|
615
|
-
|| updatedMission.status !== mission?.status
|
|
616
|
-
|| updatedMission.phase !== mission?.phase
|
|
617
|
-
|| updatedMission.currentStep !== mission?.currentStep
|
|
618
|
-
|| updatedMission.waitState?.reason !== mission?.waitState?.reason
|
|
619
|
-
)
|
|
620
|
-
)
|
|
621
588
|
const shouldSyncWorkingState = (
|
|
622
589
|
(!isHeartbeatRun && (assistantPersisted || persistedToolEvents.length > 0 || Boolean(errorMessage)))
|
|
623
|
-
|| (isHeartbeatRun && (persistedToolEvents.length > 0 || Boolean(errorMessage)
|
|
590
|
+
|| (isHeartbeatRun && (persistedToolEvents.length > 0 || Boolean(errorMessage)))
|
|
624
591
|
)
|
|
625
592
|
if (shouldSyncWorkingState) {
|
|
626
593
|
try {
|
|
627
594
|
await synchronizeWorkingStateForTurn({
|
|
628
595
|
sessionId,
|
|
629
596
|
agentId: current.agentId || null,
|
|
630
|
-
mission: updatedMission,
|
|
631
597
|
message,
|
|
632
598
|
assistantText: hiddenControlOnly ? '' : textForPersistence,
|
|
633
599
|
error: errorMessage || null,
|
|
@@ -673,7 +639,6 @@ export async function finalizeChatTurn(params: {
|
|
|
673
639
|
return {
|
|
674
640
|
runId,
|
|
675
641
|
sessionId,
|
|
676
|
-
missionId: mission?.id || null,
|
|
677
642
|
text: hiddenControlOnly ? '' : textForPersistence,
|
|
678
643
|
persisted: assistantPersisted,
|
|
679
644
|
toolEvents: persistedToolEvents,
|
|
@@ -45,9 +45,6 @@ import {
|
|
|
45
45
|
} from '@/lib/capability-selection'
|
|
46
46
|
import { normalizeProviderEndpoint, isLocalOpenClawEndpoint } from '@/lib/openclaw/openclaw-endpoint'
|
|
47
47
|
import { NON_LANGGRAPH_PROVIDER_IDS } from '@/lib/provider-sets'
|
|
48
|
-
import {
|
|
49
|
-
resolveMissionForTurn,
|
|
50
|
-
} from '@/lib/server/missions/mission-service'
|
|
51
48
|
import {
|
|
52
49
|
bridgeHumanReplyFromChat,
|
|
53
50
|
} from '@/lib/server/chatrooms/session-mailbox'
|
|
@@ -465,7 +462,7 @@ export interface PreparedExecutableChatTurn {
|
|
|
465
462
|
appSettings: ReturnType<typeof loadSettings>
|
|
466
463
|
lifecycleRunId: string
|
|
467
464
|
agentForSession: ReturnType<typeof getAgent>
|
|
468
|
-
mission:
|
|
465
|
+
mission: null
|
|
469
466
|
executionBrief: ExecutionBrief
|
|
470
467
|
executionBriefContextBlock?: string
|
|
471
468
|
extensionsForRun: string[]
|
|
@@ -503,7 +500,6 @@ export async function prepareChatTurn(input: ExecuteChatTurnInput): Promise<Prep
|
|
|
503
500
|
imagePath,
|
|
504
501
|
imageUrl,
|
|
505
502
|
attachedFiles,
|
|
506
|
-
missionId: explicitMissionId,
|
|
507
503
|
internal = false,
|
|
508
504
|
runId,
|
|
509
505
|
source = 'chat',
|
|
@@ -580,17 +576,7 @@ export async function prepareChatTurn(input: ExecuteChatTurnInput): Promise<Prep
|
|
|
580
576
|
try { syncSessionArchiveMemory(session, { agent: agentForSession }) } catch { /* best-effort */ }
|
|
581
577
|
}
|
|
582
578
|
|
|
583
|
-
const mission =
|
|
584
|
-
session,
|
|
585
|
-
message,
|
|
586
|
-
source,
|
|
587
|
-
internal,
|
|
588
|
-
runId: lifecycleRunId,
|
|
589
|
-
explicitMissionId: explicitMissionId || null,
|
|
590
|
-
})
|
|
591
|
-
if (mission?.id) {
|
|
592
|
-
session.missionId = mission.id
|
|
593
|
-
}
|
|
579
|
+
const mission = null
|
|
594
580
|
const extensionsForRun = toolPolicy.enabledExtensions
|
|
595
581
|
if (runMessageStartIndex === 0) {
|
|
596
582
|
await runCapabilityHook(
|
|
@@ -606,12 +592,6 @@ export async function prepareChatTurn(input: ExecuteChatTurnInput): Promise<Prep
|
|
|
606
592
|
let sessionForRun = JSON.stringify(runtimeCapabilityIds) === JSON.stringify(extensionsForRun)
|
|
607
593
|
? session
|
|
608
594
|
: { ...session, tools: sessionForRunSelection.tools, extensions: sessionForRunSelection.extensions }
|
|
609
|
-
if (mission?.id) {
|
|
610
|
-
sessionForRun = {
|
|
611
|
-
...sessionForRun,
|
|
612
|
-
missionId: mission.id,
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
595
|
if (agentForSession) {
|
|
616
596
|
const preferredRoute = resolvePrimaryAgentRoute(agentForSession, undefined, {
|
|
617
597
|
preferredGatewayTags: session.routePreferredGatewayTags || [],
|
|
@@ -12,8 +12,6 @@ import { canonicalizeExtensionId } from '@/lib/server/tool-aliases'
|
|
|
12
12
|
import { logExecution } from '@/lib/server/execution-log'
|
|
13
13
|
import { perf } from '@/lib/server/runtime/perf'
|
|
14
14
|
import {
|
|
15
|
-
getWalletApprovalBoundaryAction,
|
|
16
|
-
isWalletSimulationResult,
|
|
17
15
|
resolveSuccessfulTerminalToolBoundary,
|
|
18
16
|
updateStreamedToolEvents,
|
|
19
17
|
} from '@/lib/server/chat-execution/chat-streaming-utils'
|
|
@@ -21,7 +19,6 @@ import {
|
|
|
21
19
|
resolveToolAction,
|
|
22
20
|
} from '@/lib/server/chat-execution/memory-mutation-tools'
|
|
23
21
|
import {
|
|
24
|
-
hasStateChangingWalletEvidence,
|
|
25
22
|
countExternalExecutionResearchSteps,
|
|
26
23
|
countDistinctExternalResearchHosts,
|
|
27
24
|
} from '@/lib/server/chat-execution/stream-continuation'
|
|
@@ -328,18 +325,9 @@ export async function processIterationEvents(opts: ProcessIterationEventsOpts):
|
|
|
328
325
|
break
|
|
329
326
|
}
|
|
330
327
|
}
|
|
331
|
-
if (boundedExternalExecutionTask && getWalletApprovalBoundaryAction(outputStr || '')) {
|
|
332
|
-
reachedExecutionBoundary = true
|
|
333
|
-
write(`data: ${JSON.stringify({
|
|
334
|
-
t: 'status',
|
|
335
|
-
text: JSON.stringify({ executionBoundary: 'wallet_approval' }),
|
|
336
|
-
})}\n\n`)
|
|
337
|
-
break
|
|
338
|
-
}
|
|
339
328
|
if (
|
|
340
329
|
boundedExternalExecutionTask
|
|
341
330
|
&& ['http_request', 'web', 'web_search', 'web_fetch', 'browser'].includes(toolName)
|
|
342
|
-
&& !hasStateChangingWalletEvidence(state.streamedToolEvents)
|
|
343
331
|
&& countExternalExecutionResearchSteps(state.streamedToolEvents) >= 5
|
|
344
332
|
&& countDistinctExternalResearchHosts(state.streamedToolEvents) >= 3
|
|
345
333
|
) {
|
|
@@ -350,18 +338,6 @@ export async function processIterationEvents(opts: ProcessIterationEventsOpts):
|
|
|
350
338
|
})}\n\n`)
|
|
351
339
|
break
|
|
352
340
|
}
|
|
353
|
-
if (
|
|
354
|
-
boundedExternalExecutionTask
|
|
355
|
-
&& !hasStateChangingWalletEvidence(state.streamedToolEvents)
|
|
356
|
-
&& isWalletSimulationResult(toolName, outputStr || '')
|
|
357
|
-
) {
|
|
358
|
-
executionFollowthroughReason = 'post_simulation'
|
|
359
|
-
write(`data: ${JSON.stringify({
|
|
360
|
-
t: 'status',
|
|
361
|
-
text: JSON.stringify({ executionBoundary: 'post_simulation' }),
|
|
362
|
-
})}\n\n`)
|
|
363
|
-
break
|
|
364
|
-
}
|
|
365
341
|
}
|
|
366
342
|
}
|
|
367
343
|
|
|
@@ -26,7 +26,6 @@ describe('parseClassificationResponse', () => {
|
|
|
26
26
|
taskIntent: 'general',
|
|
27
27
|
isDeliverableTask: true,
|
|
28
28
|
isBroadGoal: false,
|
|
29
|
-
walletIntent: 'none',
|
|
30
29
|
hasHumanSignals: false,
|
|
31
30
|
hasSignificantEvent: false,
|
|
32
31
|
isResearchSynthesis: false,
|
|
@@ -40,7 +39,6 @@ describe('parseClassificationResponse', () => {
|
|
|
40
39
|
assert.ok(result)
|
|
41
40
|
assert.equal(result!.isDeliverableTask, true)
|
|
42
41
|
assert.equal(result!.isBroadGoal, false)
|
|
43
|
-
assert.equal(result!.walletIntent, 'none')
|
|
44
42
|
assert.equal(result!.taskIntent, 'general')
|
|
45
43
|
assert.equal(result!.workType, 'general')
|
|
46
44
|
assert.equal(result!.confidence, 0.9)
|
|
@@ -62,7 +60,6 @@ describe('parseClassificationResponse', () => {
|
|
|
62
60
|
taskIntent: 'general',
|
|
63
61
|
isDeliverableTask: true,
|
|
64
62
|
isBroadGoal: false,
|
|
65
|
-
walletIntent: 'none',
|
|
66
63
|
hasHumanSignals: false,
|
|
67
64
|
hasSignificantEvent: false,
|
|
68
65
|
isResearchSynthesis: false,
|
|
@@ -128,44 +125,6 @@ describe('isBroadGoal', () => {
|
|
|
128
125
|
})
|
|
129
126
|
})
|
|
130
127
|
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
// hasWalletIntent
|
|
133
|
-
// ---------------------------------------------------------------------------
|
|
134
|
-
|
|
135
|
-
describe('hasWalletIntent', () => {
|
|
136
|
-
it('walletIntent none returns false', () => {
|
|
137
|
-
assert.equal(mod.hasWalletIntent(makeClassification({ walletIntent: 'none' }), ''), false)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('walletIntent read_only returns true', () => {
|
|
141
|
-
assert.equal(mod.hasWalletIntent(makeClassification({ walletIntent: 'read_only' }), ''), true)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
it('walletIntent transactional returns true', () => {
|
|
145
|
-
assert.equal(mod.hasWalletIntent(makeClassification({ walletIntent: 'transactional' }), ''), true)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('falls back to regex when classification is null', () => {
|
|
149
|
-
assert.equal(mod.hasWalletIntent(null, 'check my wallet balance'), false)
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
// ---------------------------------------------------------------------------
|
|
154
|
-
// hasTransactionalWalletIntent
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
|
|
157
|
-
describe('hasTransactionalWalletIntent', () => {
|
|
158
|
-
it('only transactional returns true', () => {
|
|
159
|
-
assert.equal(mod.hasTransactionalWalletIntent(makeClassification({ walletIntent: 'transactional' }), ''), true)
|
|
160
|
-
assert.equal(mod.hasTransactionalWalletIntent(makeClassification({ walletIntent: 'read_only' }), ''), false)
|
|
161
|
-
assert.equal(mod.hasTransactionalWalletIntent(makeClassification({ walletIntent: 'none' }), ''), false)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('falls back to regex when classification is null', () => {
|
|
165
|
-
assert.equal(mod.hasTransactionalWalletIntent(null, 'swap 1 ETH for USDC'), false)
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
|
|
169
128
|
// ---------------------------------------------------------------------------
|
|
170
129
|
// hasHumanSignals
|
|
171
130
|
// ---------------------------------------------------------------------------
|
|
@@ -227,7 +186,6 @@ describe('classifyMessage', () => {
|
|
|
227
186
|
taskIntent: 'coding',
|
|
228
187
|
isDeliverableTask: true,
|
|
229
188
|
isBroadGoal: false,
|
|
230
|
-
walletIntent: 'none',
|
|
231
189
|
hasHumanSignals: false,
|
|
232
190
|
hasSignificantEvent: false,
|
|
233
191
|
isResearchSynthesis: false,
|
|
@@ -244,7 +202,6 @@ describe('classifyMessage', () => {
|
|
|
244
202
|
assert.ok(result)
|
|
245
203
|
assert.equal(result!.isDeliverableTask, true)
|
|
246
204
|
assert.equal(result!.taskIntent, 'coding')
|
|
247
|
-
assert.equal(result!.walletIntent, 'none')
|
|
248
205
|
assert.equal(result!.workType, 'coding')
|
|
249
206
|
assert.deepEqual(result!.explicitToolRequests, ['shell'])
|
|
250
207
|
})
|
|
@@ -284,7 +241,6 @@ describe('classifyMessage', () => {
|
|
|
284
241
|
taskIntent: 'general',
|
|
285
242
|
isDeliverableTask: false,
|
|
286
243
|
isBroadGoal: false,
|
|
287
|
-
walletIntent: 'none',
|
|
288
244
|
hasHumanSignals: false,
|
|
289
245
|
hasSignificantEvent: false,
|
|
290
246
|
isResearchSynthesis: false,
|
|
@@ -326,7 +282,6 @@ function makeClassification(overrides: Partial<import('@/lib/server/chat-executi
|
|
|
326
282
|
taskIntent: 'general',
|
|
327
283
|
isDeliverableTask: false,
|
|
328
284
|
isBroadGoal: false,
|
|
329
|
-
walletIntent: 'none',
|
|
330
285
|
hasHumanSignals: false,
|
|
331
286
|
hasSignificantEvent: false,
|
|
332
287
|
isResearchSynthesis: false,
|
|
@@ -32,7 +32,6 @@ export const MessageClassificationSchema = z.object({
|
|
|
32
32
|
isDeliverableTask: z.boolean(),
|
|
33
33
|
isBroadGoal: z.boolean(),
|
|
34
34
|
isLightweightDirectChat: z.boolean().optional().default(false),
|
|
35
|
-
walletIntent: z.enum(['none', 'read_only', 'transactional']),
|
|
36
35
|
hasHumanSignals: z.boolean(),
|
|
37
36
|
hasSignificantEvent: z.boolean(),
|
|
38
37
|
isResearchSynthesis: z.boolean(),
|
|
@@ -49,7 +48,6 @@ export interface MessageClassification {
|
|
|
49
48
|
isDeliverableTask: boolean
|
|
50
49
|
isBroadGoal: boolean
|
|
51
50
|
isLightweightDirectChat?: boolean
|
|
52
|
-
walletIntent: 'none' | 'read_only' | 'transactional'
|
|
53
51
|
hasHumanSignals: boolean
|
|
54
52
|
hasSignificantEvent: boolean
|
|
55
53
|
isResearchSynthesis: boolean
|
|
@@ -105,7 +103,6 @@ function buildClassificationPrompt(message: string, recentHistory: string): stri
|
|
|
105
103
|
'- isDeliverableTask (bool): The user wants a concrete artifact produced — a document, report, plan, proposal, landing page, dashboard, HTML file, markdown file, brief, copy, screenshots, or similar deliverable. NOT simple Q&A, code fixes, or single-command tasks.',
|
|
106
104
|
'- isBroadGoal (bool): The message describes a broad, multi-step goal (50+ chars, no code blocks, no file paths, no numbered lists). Short questions ending with "?" are NOT broad goals.',
|
|
107
105
|
'- isLightweightDirectChat (bool): This is a low-signal direct chat turn that should get a natural lightweight reply, such as a greeting, acknowledgment, check-in, or simple social/direct question that does NOT require research, file work, planning, delegation, or tool execution.',
|
|
108
|
-
'- walletIntent: "none" if no crypto/wallet/trading context. "read_only" if mentioning wallet/crypto but only for checking balances, viewing transactions, or research. "transactional" if the user wants to swap, trade, buy, sell, mint, claim, deposit, withdraw, bridge, or execute a transaction.',
|
|
109
106
|
'- hasHumanSignals (bool): The message contains personal signals — preferences ("I prefer", "call me"), relationships ("my wife", "my partner", "my kid"), life events ("birthday", "wedding", "promotion", "moving", "graduation", "hospital"), or personal disclosures.',
|
|
110
107
|
'- hasSignificantEvent (bool): The message mentions a notable life/work event or milestone (birthday, anniversary, wedding, graduation, promotion, new job, relocation, illness, funeral, travel, house, deadline, launch).',
|
|
111
108
|
'- isResearchSynthesis (bool): The task requires gathering information from multiple sources and synthesizing it — research reports, competitive analysis, market overviews, literature reviews, multi-source comparisons. NOT simple factual lookups.',
|
|
@@ -120,12 +117,11 @@ function buildClassificationPrompt(message: string, recentHistory: string): stri
|
|
|
120
117
|
'- Be conservative. When unsure, default to false/none/empty.',
|
|
121
118
|
'- Mark isLightweightDirectChat true only when a short natural reply is enough and escalating into planning, delegation, or tool execution would be unnecessary.',
|
|
122
119
|
'- A message can be both a deliverable task AND a broad goal.',
|
|
123
|
-
'- "walletIntent" should be "transactional" only if the user wants to execute a state-changing action, not just discuss crypto.',
|
|
124
120
|
'- For "explicitToolRequests", only include tools the user explicitly mentions by name or clear synonym. Do not infer tool needs from the task type.',
|
|
125
121
|
'- Prefer the most execution-relevant taskIntent. Example: "research this and send me a voice note" is "research", not "outreach".',
|
|
126
122
|
'',
|
|
127
123
|
'Output shape:',
|
|
128
|
-
'{"taskIntent":"coding|research|browsing|outreach|scheduling|general","isDeliverableTask":bool,"isBroadGoal":bool,"isLightweightDirectChat":bool,"
|
|
124
|
+
'{"taskIntent":"coding|research|browsing|outreach|scheduling|general","isDeliverableTask":bool,"isBroadGoal":bool,"isLightweightDirectChat":bool,"hasHumanSignals":bool,"hasSignificantEvent":bool,"isResearchSynthesis":bool,"workType":"coding|research|writing|review|operations|general","wantsScreenshots":bool,"wantsOutboundDelivery":bool,"wantsVoiceDelivery":bool,"explicitToolRequests":[],"confidence":0.0-1.0}',
|
|
129
125
|
'',
|
|
130
126
|
recentHistory ? `Recent context:\n${recentHistory}\n` : '',
|
|
131
127
|
`User message: ${JSON.stringify(message)}`,
|
|
@@ -276,7 +272,6 @@ export function toMessageSemanticsSummary(classification: MessageClassification
|
|
|
276
272
|
return {
|
|
277
273
|
taskIntent: classification.taskIntent,
|
|
278
274
|
workType: classification.workType || 'general',
|
|
279
|
-
walletIntent: classification.walletIntent,
|
|
280
275
|
isDeliverableTask: classification.isDeliverableTask,
|
|
281
276
|
isBroadGoal: classification.isBroadGoal,
|
|
282
277
|
isResearchSynthesis: classification.isResearchSynthesis,
|
|
@@ -305,16 +300,6 @@ export function isBroadGoal(classification: MessageClassification | null, messag
|
|
|
305
300
|
return classification?.isBroadGoal === true
|
|
306
301
|
}
|
|
307
302
|
|
|
308
|
-
export function hasWalletIntent(classification: MessageClassification | null, message?: string): boolean {
|
|
309
|
-
void message
|
|
310
|
-
return classification?.walletIntent !== undefined && classification.walletIntent !== 'none'
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export function hasTransactionalWalletIntent(classification: MessageClassification | null, message?: string): boolean {
|
|
314
|
-
void message
|
|
315
|
-
return classification?.walletIntent === 'transactional'
|
|
316
|
-
}
|
|
317
|
-
|
|
318
303
|
export function hasHumanSignals(classification: MessageClassification | null, transcript?: string): boolean {
|
|
319
304
|
void transcript
|
|
320
305
|
return classification?.hasHumanSignals === true
|