@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
|
@@ -24,8 +24,6 @@ import type {
|
|
|
24
24
|
GuardianCheckpoint,
|
|
25
25
|
LearnedSkill,
|
|
26
26
|
Message,
|
|
27
|
-
Mission,
|
|
28
|
-
MissionEvent,
|
|
29
27
|
ProtocolTemplate,
|
|
30
28
|
ProtocolRun,
|
|
31
29
|
ProtocolRunEvent,
|
|
@@ -138,9 +136,6 @@ const COLLECTIONS = [
|
|
|
138
136
|
'webhook_retry_queue',
|
|
139
137
|
'notifications',
|
|
140
138
|
'chatrooms',
|
|
141
|
-
'wallets',
|
|
142
|
-
'wallet_transactions',
|
|
143
|
-
'wallet_balance_history',
|
|
144
139
|
'moderation_logs',
|
|
145
140
|
'connector_health',
|
|
146
141
|
'connector_outbox',
|
|
@@ -152,8 +147,6 @@ const COLLECTIONS = [
|
|
|
152
147
|
'watch_jobs',
|
|
153
148
|
'delegation_jobs',
|
|
154
149
|
'external_agents',
|
|
155
|
-
'missions',
|
|
156
|
-
'mission_events',
|
|
157
150
|
'protocol_templates',
|
|
158
151
|
'protocol_runs',
|
|
159
152
|
'protocol_run_events',
|
|
@@ -162,6 +155,8 @@ const COLLECTIONS = [
|
|
|
162
155
|
'main_loop_states',
|
|
163
156
|
'working_states',
|
|
164
157
|
'daemon_status',
|
|
158
|
+
'wallets',
|
|
159
|
+
'wallet_transactions',
|
|
165
160
|
] as const
|
|
166
161
|
|
|
167
162
|
export type StorageCollection = (typeof COLLECTIONS)[number]
|
|
@@ -545,8 +540,6 @@ const JSON_FILES: Record<string, string> = {
|
|
|
545
540
|
documents: path.join(DATA_DIR, 'documents.json'),
|
|
546
541
|
webhooks: path.join(DATA_DIR, 'webhooks.json'),
|
|
547
542
|
external_agents: path.join(DATA_DIR, 'external-agents.json'),
|
|
548
|
-
missions: path.join(DATA_DIR, 'missions.json'),
|
|
549
|
-
mission_events: path.join(DATA_DIR, 'mission-events.json'),
|
|
550
543
|
protocol_templates: path.join(DATA_DIR, 'protocol-templates.json'),
|
|
551
544
|
protocol_runs: path.join(DATA_DIR, 'protocol-runs.json'),
|
|
552
545
|
protocol_run_events: path.join(DATA_DIR, 'protocol-run-events.json'),
|
|
@@ -1208,25 +1201,6 @@ export const loadProjects = projectsStore.load
|
|
|
1208
1201
|
export const saveProjects = projectsStore.save
|
|
1209
1202
|
export const deleteProject = projectsStore.deleteItem
|
|
1210
1203
|
|
|
1211
|
-
// --- Missions ---
|
|
1212
|
-
const missionsStore = createCollectionStore('missions')
|
|
1213
|
-
export const loadMissions = missionsStore.load as () => Record<string, Mission>
|
|
1214
|
-
export const saveMissions = missionsStore.save as (items: Record<string, Mission>) => void
|
|
1215
|
-
export const loadMission = missionsStore.loadItem as (id: string) => Mission | null
|
|
1216
|
-
export const upsertMission = missionsStore.upsert as (id: string, value: Mission) => void
|
|
1217
|
-
export const patchMission = missionsStore.patch as (
|
|
1218
|
-
id: string,
|
|
1219
|
-
updater: (current: Mission | null) => Mission | null,
|
|
1220
|
-
) => Mission | null
|
|
1221
|
-
export const deleteMission = missionsStore.deleteItem
|
|
1222
|
-
|
|
1223
|
-
const missionEventsStore = createCollectionStore('mission_events')
|
|
1224
|
-
export const loadMissionEvents = missionEventsStore.load as () => Record<string, MissionEvent>
|
|
1225
|
-
export const saveMissionEvents = missionEventsStore.save as (items: Record<string, MissionEvent>) => void
|
|
1226
|
-
export const loadMissionEvent = missionEventsStore.loadItem as (id: string) => MissionEvent | null
|
|
1227
|
-
export const upsertMissionEvent = missionEventsStore.upsert as (id: string, value: MissionEvent) => void
|
|
1228
|
-
export const upsertMissionEvents = missionEventsStore.upsertMany as (entries: Array<[string, MissionEvent]>) => void
|
|
1229
|
-
|
|
1230
1204
|
const protocolTemplatesStore = createCollectionStore('protocol_templates')
|
|
1231
1205
|
export const loadProtocolTemplates = protocolTemplatesStore.load as () => Record<string, ProtocolTemplate>
|
|
1232
1206
|
export const saveProtocolTemplates = protocolTemplatesStore.save as (items: Record<string, ProtocolTemplate>) => void
|
|
@@ -1541,23 +1515,6 @@ export function markNotificationRead(id: string) {
|
|
|
1541
1515
|
}
|
|
1542
1516
|
}
|
|
1543
1517
|
|
|
1544
|
-
// --- Wallets ---
|
|
1545
|
-
const walletsStore = createCollectionStore('wallets')
|
|
1546
|
-
export const loadWallets = walletsStore.load
|
|
1547
|
-
export const upsertWallet = walletsStore.upsert
|
|
1548
|
-
export const deleteWallet = walletsStore.deleteItem
|
|
1549
|
-
|
|
1550
|
-
// --- Wallet Transactions ---
|
|
1551
|
-
const walletTransactionsStore = createCollectionStore('wallet_transactions')
|
|
1552
|
-
export const loadWalletTransactions = walletTransactionsStore.load
|
|
1553
|
-
export const upsertWalletTransaction = walletTransactionsStore.upsert
|
|
1554
|
-
export const deleteWalletTransaction = walletTransactionsStore.deleteItem
|
|
1555
|
-
|
|
1556
|
-
// --- Wallet Balance History ---
|
|
1557
|
-
const walletBalanceHistoryStore = createCollectionStore('wallet_balance_history')
|
|
1558
|
-
export const loadWalletBalanceHistory = walletBalanceHistoryStore.load
|
|
1559
|
-
export const upsertWalletBalanceSnapshot = walletBalanceHistoryStore.upsert
|
|
1560
|
-
|
|
1561
1518
|
// --- Moderation Logs ---
|
|
1562
1519
|
const moderationLogsStore = createCollectionStore('moderation_logs')
|
|
1563
1520
|
export const loadModerationLogs = moderationLogsStore.load
|
|
@@ -1613,6 +1570,22 @@ export const loadPersistedWorkingState = workingStatesStore.loadItem
|
|
|
1613
1570
|
export const upsertPersistedWorkingState = workingStatesStore.upsert
|
|
1614
1571
|
export const deletePersistedWorkingState = workingStatesStore.deleteItem
|
|
1615
1572
|
|
|
1573
|
+
// --- Wallets ---
|
|
1574
|
+
const walletsStore = createCollectionStore('wallets')
|
|
1575
|
+
export const loadWallets = walletsStore.load
|
|
1576
|
+
export const saveWallets = walletsStore.save
|
|
1577
|
+
export const loadWallet = walletsStore.loadItem
|
|
1578
|
+
export const upsertWallet = walletsStore.upsert
|
|
1579
|
+
export const deleteWalletItem = walletsStore.deleteItem
|
|
1580
|
+
|
|
1581
|
+
// --- Wallet Transactions ---
|
|
1582
|
+
const walletTransactionsStore = createCollectionStore('wallet_transactions')
|
|
1583
|
+
export const loadWalletTransactions = walletTransactionsStore.load
|
|
1584
|
+
export const saveWalletTransactions = walletTransactionsStore.save
|
|
1585
|
+
export const loadWalletTransaction = walletTransactionsStore.loadItem
|
|
1586
|
+
export const upsertWalletTransaction = walletTransactionsStore.upsert
|
|
1587
|
+
export const deleteWalletTransaction = walletTransactionsStore.deleteItem
|
|
1588
|
+
|
|
1616
1589
|
export function getSessionMessages(sessionId: string): Message[] {
|
|
1617
1590
|
const session = loadSession(sessionId)
|
|
1618
1591
|
return Array.isArray(session?.messages) ? session.messages : []
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { BoardTask } from '@/types'
|
|
2
|
+
import { withTransaction } from '@/lib/server/persistence/transaction'
|
|
3
|
+
import { loadTasks, saveTasks } from '@/lib/server/tasks/task-repository'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Atomically transition a task from queued → running with a checkout run ID.
|
|
7
|
+
*
|
|
8
|
+
* Uses a SQLite IMMEDIATE transaction to prevent two runners from starting the
|
|
9
|
+
* same task concurrently (Paperclip-inspired atomic checkout pattern).
|
|
10
|
+
*
|
|
11
|
+
* Returns the checked-out task on success, or null if the task was already
|
|
12
|
+
* taken, missing, or no longer in queued status.
|
|
13
|
+
*/
|
|
14
|
+
export function checkoutTask(
|
|
15
|
+
taskId: string,
|
|
16
|
+
runId: string,
|
|
17
|
+
): BoardTask | null {
|
|
18
|
+
return withTransaction(() => {
|
|
19
|
+
const tasks = loadTasks() as Record<string, BoardTask>
|
|
20
|
+
const task = tasks[taskId]
|
|
21
|
+
if (!task || task.status !== 'queued') return null
|
|
22
|
+
if (task.checkoutRunId) return null // already checked out
|
|
23
|
+
|
|
24
|
+
const now = Date.now()
|
|
25
|
+
task.status = 'running'
|
|
26
|
+
task.checkoutRunId = runId
|
|
27
|
+
task.startedAt = now
|
|
28
|
+
task.lastActivityAt = now
|
|
29
|
+
task.retryScheduledAt = null
|
|
30
|
+
task.deadLetteredAt = null
|
|
31
|
+
task.error = null
|
|
32
|
+
task.validation = null
|
|
33
|
+
task.updatedAt = now
|
|
34
|
+
|
|
35
|
+
saveTasks(tasks)
|
|
36
|
+
return { ...task }
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Release a checkout after task completion or failure.
|
|
42
|
+
* Only the holder of the checkout (matching runId) can release it.
|
|
43
|
+
*/
|
|
44
|
+
export function releaseCheckout(
|
|
45
|
+
taskId: string,
|
|
46
|
+
runId: string,
|
|
47
|
+
): boolean {
|
|
48
|
+
return withTransaction(() => {
|
|
49
|
+
const tasks = loadTasks() as Record<string, BoardTask>
|
|
50
|
+
const task = tasks[taskId]
|
|
51
|
+
if (!task) return false
|
|
52
|
+
if (task.checkoutRunId !== runId) return false
|
|
53
|
+
|
|
54
|
+
task.checkoutRunId = null
|
|
55
|
+
task.updatedAt = Date.now()
|
|
56
|
+
saveTasks(tasks)
|
|
57
|
+
return true
|
|
58
|
+
})
|
|
59
|
+
}
|
|
@@ -176,6 +176,7 @@ export function markValidatedTaskCompleted(
|
|
|
176
176
|
task.completedAt = options.preserveCompletedAt ? (task.completedAt || options.now) : options.now
|
|
177
177
|
task.updatedAt = options.now
|
|
178
178
|
task.error = null
|
|
179
|
+
task.checkoutRunId = null
|
|
179
180
|
return task
|
|
180
181
|
}
|
|
181
182
|
|
|
@@ -187,6 +188,7 @@ export function markInvalidCompletedTaskFailed(
|
|
|
187
188
|
task.status = 'failed'
|
|
188
189
|
task.completedAt = null
|
|
189
190
|
task.updatedAt = options.now
|
|
191
|
+
task.checkoutRunId = null
|
|
190
192
|
task.error = formatValidationFailure(validation.reasons).slice(0, 500)
|
|
191
193
|
if (options.comment) {
|
|
192
194
|
if (!task.comments) task.comments = []
|
|
@@ -6,11 +6,6 @@ import { logActivity } from '@/lib/server/activity/activity-log'
|
|
|
6
6
|
import { createNotification } from '@/lib/server/create-notification'
|
|
7
7
|
import { validateDag, cascadeUnblock } from '@/lib/server/dag-validation'
|
|
8
8
|
import { getExtensionManager } from '@/lib/server/extensions'
|
|
9
|
-
import {
|
|
10
|
-
enrichTaskWithMissionSummary,
|
|
11
|
-
ensureMissionForTask,
|
|
12
|
-
noteMissionTaskFinished,
|
|
13
|
-
} from '@/lib/server/missions/mission-service'
|
|
14
9
|
import {
|
|
15
10
|
disableSessionHeartbeat,
|
|
16
11
|
enqueueTask,
|
|
@@ -64,9 +59,7 @@ export function prepareTasksForListing() {
|
|
|
64
59
|
validateCompletedTasksQueue()
|
|
65
60
|
recoverStalledRunningTasks()
|
|
66
61
|
const allTasks = loadTasks()
|
|
67
|
-
return
|
|
68
|
-
Object.entries(allTasks).map(([id, task]) => [id, enrichTaskWithMissionSummary(task)]),
|
|
69
|
-
)
|
|
62
|
+
return allTasks
|
|
70
63
|
}
|
|
71
64
|
|
|
72
65
|
export function updateTaskFromRoute(id: string, body: Record<string, unknown>): ServiceResult<BoardTask> {
|
|
@@ -128,10 +121,6 @@ export function updateTaskFromRoute(id: string, body: Record<string, unknown>):
|
|
|
128
121
|
}
|
|
129
122
|
|
|
130
123
|
saveTask(id, tasks[id])
|
|
131
|
-
const mission = ensureMissionForTask(tasks[id], { source: 'manual' })
|
|
132
|
-
if (tasks[id].status === 'completed' || tasks[id].status === 'failed' || tasks[id].status === 'cancelled') {
|
|
133
|
-
noteMissionTaskFinished(tasks[id], tasks[id].status, tasks[id].id)
|
|
134
|
-
}
|
|
135
124
|
logActivity({ entityType: 'task', entityId: id, action: 'updated', actor: 'user', summary: `Task updated: "${tasks[id].title}" (${prevStatus} → ${tasks[id].status})` })
|
|
136
125
|
if (prevStatus !== tasks[id].status) {
|
|
137
126
|
pushMainLoopEventToMainSessions({
|
|
@@ -143,10 +132,7 @@ export function updateTaskFromRoute(id: string, body: Record<string, unknown>):
|
|
|
143
132
|
if (prevStatus !== tasks[id].status && tasks[id].status === 'cancelled') {
|
|
144
133
|
disableSessionHeartbeat(tasks[id].sessionId)
|
|
145
134
|
notify('tasks')
|
|
146
|
-
return serviceOk(
|
|
147
|
-
...tasks[id],
|
|
148
|
-
missionId: mission?.id || tasks[id].missionId || null,
|
|
149
|
-
}))
|
|
135
|
+
return serviceOk(tasks[id])
|
|
150
136
|
}
|
|
151
137
|
|
|
152
138
|
if (prevStatus !== tasks[id].status && (tasks[id].status === 'completed' || tasks[id].status === 'failed')) {
|
|
@@ -216,10 +202,7 @@ export function updateTaskFromRoute(id: string, body: Record<string, unknown>):
|
|
|
216
202
|
}
|
|
217
203
|
|
|
218
204
|
notify('tasks')
|
|
219
|
-
return serviceOk(
|
|
220
|
-
...tasks[id],
|
|
221
|
-
missionId: mission?.id || tasks[id].missionId || null,
|
|
222
|
-
}))
|
|
205
|
+
return serviceOk(tasks[id])
|
|
223
206
|
}
|
|
224
207
|
|
|
225
208
|
export function archiveTaskFromRoute(id: string): ServiceResult<BoardTask> {
|
|
@@ -346,11 +329,6 @@ export function createTaskFromRoute(body: Record<string, unknown>): ServiceResul
|
|
|
346
329
|
}
|
|
347
330
|
|
|
348
331
|
saveTask(id, task)
|
|
349
|
-
const mission = ensureMissionForTask(task, { source: 'manual' })
|
|
350
|
-
const finalTask = enrichTaskWithMissionSummary({
|
|
351
|
-
...task,
|
|
352
|
-
missionId: mission?.id || task.missionId || null,
|
|
353
|
-
})
|
|
354
332
|
logActivity({ entityType: 'task', entityId: id, action: 'created', actor: 'user', summary: `Task created: "${task.title}"` })
|
|
355
333
|
pushMainLoopEventToMainSessions({
|
|
356
334
|
type: 'task_created',
|
|
@@ -360,7 +338,7 @@ export function createTaskFromRoute(body: Record<string, unknown>): ServiceResul
|
|
|
360
338
|
enqueueTask(id)
|
|
361
339
|
}
|
|
362
340
|
notify('tasks')
|
|
363
|
-
return serviceOk(
|
|
341
|
+
return serviceOk(task)
|
|
364
342
|
}
|
|
365
343
|
|
|
366
344
|
export function bulkUpdateTasksFromRoute(body: Record<string, unknown>): ServiceResult<{ updated: number; ids: string[] }> {
|
|
@@ -106,13 +106,6 @@ export function applyTaskContinuationDefaults(
|
|
|
106
106
|
if (!Object.prototype.hasOwnProperty.call(explicit, 'cwd') && typeof sourceTask.cwd === 'string' && sourceTask.cwd.trim()) {
|
|
107
107
|
parsed.cwd = sourceTask.cwd.trim()
|
|
108
108
|
}
|
|
109
|
-
if (
|
|
110
|
-
!Object.prototype.hasOwnProperty.call(explicit, 'missionId')
|
|
111
|
-
&& typeof sourceTask.missionId === 'string'
|
|
112
|
-
&& sourceTask.missionId.trim()
|
|
113
|
-
) {
|
|
114
|
-
parsed.missionId = sourceTask.missionId.trim()
|
|
115
|
-
}
|
|
116
109
|
const sourceSessionId = typeof sourceTask.checkpoint?.lastSessionId === 'string' && sourceTask.checkpoint.lastSessionId.trim()
|
|
117
110
|
? sourceTask.checkpoint.lastSessionId.trim()
|
|
118
111
|
: typeof sourceTask.sessionId === 'string' && sourceTask.sessionId.trim()
|
|
@@ -22,7 +22,6 @@ const EXTENSION_ALIAS_GROUPS: string[][] = [
|
|
|
22
22
|
['schedule_wake', 'schedule'],
|
|
23
23
|
// http_request/http now aliased into web group above
|
|
24
24
|
['memory', 'memory_tool', 'memory_search', 'memory_get', 'memory_store', 'memory_update'],
|
|
25
|
-
['wallet', 'wallet_tool'],
|
|
26
25
|
['monitor', 'monitor_tool'],
|
|
27
26
|
['context_mgmt', 'context_status', 'context_summarize'],
|
|
28
27
|
['openclaw_workspace'],
|
|
@@ -423,17 +423,17 @@ describe('compound scenarios', () => {
|
|
|
423
423
|
assert.match(tasksBlock.reason, /task management is disabled/)
|
|
424
424
|
})
|
|
425
425
|
|
|
426
|
-
it('
|
|
426
|
+
it('19 tools requested: correctly partitioned into enabled vs blocked', () => {
|
|
427
427
|
const tools = [
|
|
428
428
|
'shell', 'files', 'web', 'web_search', 'web_fetch', 'browser',
|
|
429
429
|
'memory', 'delegate', 'manage_platform', 'manage_tasks',
|
|
430
|
-
'manage_schedules', 'wallet', 'delete_file',
|
|
430
|
+
'manage_schedules', 'wallet', 'delete_file',
|
|
431
431
|
'manage_connectors', 'git', 'sandbox', 'claude_code',
|
|
432
432
|
'monitor', 'http_request',
|
|
433
433
|
]
|
|
434
434
|
const d = resolveSessionToolPolicy(tools, { capabilityPolicyMode: 'strict' })
|
|
435
|
-
assert.equal(d.requestedExtensions.length,
|
|
436
|
-
assert.equal(d.enabledExtensions.length + d.blockedExtensions.length,
|
|
435
|
+
assert.equal(d.requestedExtensions.length, 19)
|
|
436
|
+
assert.equal(d.enabledExtensions.length + d.blockedExtensions.length, 19)
|
|
437
437
|
|
|
438
438
|
// memory, web, web_search, web_fetch should be enabled
|
|
439
439
|
assert.ok(d.enabledExtensions.includes('memory'))
|
|
@@ -60,8 +60,6 @@ const TOOL_DESCRIPTORS: Record<string, ToolDescriptor> = {
|
|
|
60
60
|
gemini_cli: { categories: ['delegation', 'execution'], concreteTools: ['delegate_to_gemini_cli'] },
|
|
61
61
|
memory: { categories: ['memory'], concreteTools: ['memory', 'memory_tool', 'memory_search', 'memory_get', 'memory_store', 'memory_update', 'context_status', 'context_summarize'] },
|
|
62
62
|
// http_request consolidated into web 'api' action — no separate descriptor
|
|
63
|
-
canvas: { categories: ['filesystem'], concreteTools: ['canvas'] },
|
|
64
|
-
wallet: { categories: ['outbound'], concreteTools: ['wallet', 'wallet_tool'] },
|
|
65
63
|
monitor: { categories: ['execution'], concreteTools: ['monitor', 'monitor_tool'] },
|
|
66
64
|
openclaw_workspace: { categories: ['filesystem', 'platform'], concreteTools: ['openclaw_workspace'] },
|
|
67
65
|
openclaw_nodes: { categories: ['platform'], concreteTools: ['openclaw_nodes'] },
|
|
@@ -13,8 +13,6 @@ export const TOOL_CAPABILITY = {
|
|
|
13
13
|
deliveryMessage: 'delivery.message',
|
|
14
14
|
deliveryMedia: 'delivery.media',
|
|
15
15
|
deliveryVoiceNote: 'delivery.voice_note',
|
|
16
|
-
walletInspect: 'wallet.inspect',
|
|
17
|
-
walletExecute: 'wallet.execute',
|
|
18
16
|
} as const
|
|
19
17
|
|
|
20
18
|
export interface ToolPlanningEntry {
|
|
@@ -373,16 +371,6 @@ const CORE_TOOL_PLANNING: Record<string, LegacyToolPlanningEntry[]> = {
|
|
|
373
371
|
requestMatchers: [],
|
|
374
372
|
},
|
|
375
373
|
],
|
|
376
|
-
wallet: [
|
|
377
|
-
{
|
|
378
|
-
toolName: 'wallet_tool',
|
|
379
|
-
capabilities: [TOOL_CAPABILITY.walletInspect, TOOL_CAPABILITY.walletExecute],
|
|
380
|
-
disciplineGuidance: [
|
|
381
|
-
'Inspect wallet state once, then act. Use `simulate_transaction` to validate before executing. Do not re-inspect balances between each operation unless the operation changes them.',
|
|
382
|
-
],
|
|
383
|
-
requestMatchers: [],
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
374
|
image_gen: [
|
|
387
375
|
{
|
|
388
376
|
toolName: 'generate_image',
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { encryptKey, decryptKey } from '@/lib/server/storage'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate a new Ethereum wallet (Base L2 compatible) with an encrypted private key.
|
|
5
|
+
* Uses ethers v6 for keypair generation and the existing AES-256-GCM encryption
|
|
6
|
+
* from storage.ts (CREDENTIAL_SECRET env var).
|
|
7
|
+
*/
|
|
8
|
+
export async function generateEthereumWallet(): Promise<{ address: string; encryptedPrivateKey: string }> {
|
|
9
|
+
const { Wallet } = await import('ethers')
|
|
10
|
+
const wallet = Wallet.createRandom()
|
|
11
|
+
const encryptedPrivateKey = encryptKey(wallet.privateKey)
|
|
12
|
+
return {
|
|
13
|
+
address: wallet.address,
|
|
14
|
+
encryptedPrivateKey,
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function normalizeEthereumAddress(address: string): Promise<string | null> {
|
|
19
|
+
const { getAddress } = await import('ethers')
|
|
20
|
+
try {
|
|
21
|
+
return getAddress(address.trim())
|
|
22
|
+
} catch {
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Decrypt a wallet's private key for server-side use only.
|
|
29
|
+
* Never expose the result to API responses or the frontend.
|
|
30
|
+
*/
|
|
31
|
+
export function decryptWalletPrivateKey(encrypted: string): string {
|
|
32
|
+
return decryptKey(encrypted)
|
|
33
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadWallets as loadWalletsStore,
|
|
3
|
+
saveWallets as saveWalletsStore,
|
|
4
|
+
loadWallet as loadWalletItem,
|
|
5
|
+
upsertWallet,
|
|
6
|
+
deleteWalletItem,
|
|
7
|
+
} from '@/lib/server/storage'
|
|
8
|
+
import type { AgentWallet } from '@/types/swarmdock'
|
|
9
|
+
|
|
10
|
+
export function loadWallets(): Record<string, AgentWallet> {
|
|
11
|
+
return loadWalletsStore() as Record<string, AgentWallet>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function loadWallet(id: string): AgentWallet | null {
|
|
15
|
+
return loadWalletItem(id) as AgentWallet | null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function saveWallet(id: string, wallet: AgentWallet): void {
|
|
19
|
+
upsertWallet(id, wallet)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function deleteWallet(id: string): void {
|
|
23
|
+
deleteWalletItem(id)
|
|
24
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { genId } from '@/lib/id'
|
|
2
|
+
import { loadWallets, loadWallet, saveWallet, deleteWallet } from './wallet-repository'
|
|
3
|
+
import { generateEthereumWallet, normalizeEthereumAddress } from './wallet-crypto'
|
|
4
|
+
import { logActivity } from '@/lib/server/activity/activity-log'
|
|
5
|
+
import { loadAgent } from '@/lib/server/agents/agent-repository'
|
|
6
|
+
import type { AgentWallet, SafeWallet } from '@/types/swarmdock'
|
|
7
|
+
|
|
8
|
+
export class WalletServiceError extends Error {
|
|
9
|
+
status: number
|
|
10
|
+
|
|
11
|
+
constructor(status: number, message: string) {
|
|
12
|
+
super(message)
|
|
13
|
+
this.name = 'WalletServiceError'
|
|
14
|
+
this.status = status
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function stripPrivateKey(wallet: AgentWallet): SafeWallet {
|
|
19
|
+
const { encryptedPrivateKey: _, ...safe } = wallet
|
|
20
|
+
return safe
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function requireAgent(agentId: string): string {
|
|
24
|
+
const normalizedAgentId = agentId.trim()
|
|
25
|
+
if (!normalizedAgentId) {
|
|
26
|
+
throw new WalletServiceError(400, 'agentId is required')
|
|
27
|
+
}
|
|
28
|
+
if (!loadAgent(normalizedAgentId)) {
|
|
29
|
+
throw new WalletServiceError(404, `Agent not found: ${normalizedAgentId}`)
|
|
30
|
+
}
|
|
31
|
+
return normalizedAgentId
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function requireWalletAddress(walletAddress: string): Promise<string> {
|
|
35
|
+
const normalizedAddress = walletAddress.trim()
|
|
36
|
+
if (!normalizedAddress) {
|
|
37
|
+
throw new WalletServiceError(400, 'walletAddress is required')
|
|
38
|
+
}
|
|
39
|
+
const checksumAddress = await normalizeEthereumAddress(normalizedAddress)
|
|
40
|
+
if (!checksumAddress) {
|
|
41
|
+
throw new WalletServiceError(400, 'walletAddress must be a valid Base/Ethereum address')
|
|
42
|
+
}
|
|
43
|
+
return checksumAddress
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function listWalletsSafe(): Record<string, SafeWallet> {
|
|
47
|
+
const wallets = loadWallets()
|
|
48
|
+
const safe: Record<string, SafeWallet> = {}
|
|
49
|
+
for (const [id, w] of Object.entries(wallets)) {
|
|
50
|
+
safe[id] = stripPrivateKey(w)
|
|
51
|
+
}
|
|
52
|
+
return safe
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getWalletSafe(id: string): SafeWallet | null {
|
|
56
|
+
const wallet = loadWallet(id)
|
|
57
|
+
return wallet ? stripPrivateKey(wallet) : null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Generate a new Base L2 Ethereum wallet with encrypted private key storage. */
|
|
61
|
+
export async function generateWallet(params: { agentId: string; label?: string }): Promise<SafeWallet> {
|
|
62
|
+
const agentId = requireAgent(params.agentId)
|
|
63
|
+
const { address, encryptedPrivateKey } = await generateEthereumWallet()
|
|
64
|
+
const id = genId()
|
|
65
|
+
const wallet: AgentWallet = {
|
|
66
|
+
id,
|
|
67
|
+
agentId,
|
|
68
|
+
walletAddress: address,
|
|
69
|
+
chain: 'base',
|
|
70
|
+
label: params.label || 'Base L2 Wallet',
|
|
71
|
+
encryptedPrivateKey,
|
|
72
|
+
requireApproval: true,
|
|
73
|
+
createdAt: Date.now(),
|
|
74
|
+
}
|
|
75
|
+
saveWallet(id, wallet)
|
|
76
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet generated: ${address}` })
|
|
77
|
+
return stripPrivateKey(wallet)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Create a wallet from an existing address (no key generation). */
|
|
81
|
+
export async function createWallet(params: { agentId: string; walletAddress: string; label?: string }): Promise<SafeWallet> {
|
|
82
|
+
const agentId = requireAgent(params.agentId)
|
|
83
|
+
const walletAddress = await requireWalletAddress(params.walletAddress)
|
|
84
|
+
const id = genId()
|
|
85
|
+
const wallet: AgentWallet = {
|
|
86
|
+
id,
|
|
87
|
+
agentId,
|
|
88
|
+
walletAddress,
|
|
89
|
+
chain: 'base',
|
|
90
|
+
label: params.label,
|
|
91
|
+
createdAt: Date.now(),
|
|
92
|
+
}
|
|
93
|
+
saveWallet(id, wallet)
|
|
94
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet created: ${walletAddress}` })
|
|
95
|
+
return stripPrivateKey(wallet)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Update wallet settings (label, limits, approval). */
|
|
99
|
+
export function updateWallet(
|
|
100
|
+
id: string,
|
|
101
|
+
patch: Partial<Pick<AgentWallet, 'label' | 'spendingLimitUsdc' | 'dailyLimitUsdc' | 'requireApproval'>>,
|
|
102
|
+
): SafeWallet | null {
|
|
103
|
+
const wallet = loadWallet(id)
|
|
104
|
+
if (!wallet) return null
|
|
105
|
+
if (patch.label !== undefined) wallet.label = patch.label
|
|
106
|
+
if (patch.spendingLimitUsdc !== undefined) wallet.spendingLimitUsdc = patch.spendingLimitUsdc
|
|
107
|
+
if (patch.dailyLimitUsdc !== undefined) wallet.dailyLimitUsdc = patch.dailyLimitUsdc
|
|
108
|
+
if (patch.requireApproval !== undefined) wallet.requireApproval = patch.requireApproval
|
|
109
|
+
saveWallet(id, wallet)
|
|
110
|
+
return stripPrivateKey(wallet)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function removeWallet(id: string): boolean {
|
|
114
|
+
const wallet = loadWallet(id)
|
|
115
|
+
if (!wallet) return false
|
|
116
|
+
deleteWallet(id)
|
|
117
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'deleted', actor: 'user', summary: `Wallet deleted: ${wallet.walletAddress}` })
|
|
118
|
+
return true
|
|
119
|
+
}
|
|
@@ -22,7 +22,6 @@ import type {
|
|
|
22
22
|
import {
|
|
23
23
|
EXTRACTION_TIMEOUT_MS,
|
|
24
24
|
WorkingStatePatchSchema,
|
|
25
|
-
missionStatusToWorkingStateStatus,
|
|
26
25
|
normalizeEvidenceIds,
|
|
27
26
|
now,
|
|
28
27
|
} from '@/lib/server/working-state/normalization'
|
|
@@ -268,9 +267,9 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
268
267
|
'You maintain a structured working-state object for an autonomous agent.',
|
|
269
268
|
'Return JSON only.',
|
|
270
269
|
'',
|
|
271
|
-
'Update the state using only evidence from the latest turn
|
|
270
|
+
'Update the state using only evidence from the latest turn and tool results.',
|
|
272
271
|
'Rules:',
|
|
273
|
-
'- Facts must be confirmed by explicit user text
|
|
272
|
+
'- Facts must be confirmed by explicit user text or tool evidence. Do not turn guesses into facts.',
|
|
274
273
|
'- Put uncertain leads into hypotheses, not facts.',
|
|
275
274
|
'- Use blockers for approvals, credentials, human input, external waits, and explicit execution failures.',
|
|
276
275
|
'- nextAction must be one concrete immediate action, not a broad plan.',
|
|
@@ -288,7 +287,7 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
288
287
|
status: 'idle|progress|blocked|waiting|completed',
|
|
289
288
|
nextAction: 'optional',
|
|
290
289
|
planSteps: [{ id: 'optional', text: 'step', status: 'active|resolved|superseded' }],
|
|
291
|
-
factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|
|
|
290
|
+
factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|system', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
292
291
|
artifactsUpsert: [{ id: 'optional', label: 'artifact', kind: 'file|url|approval|message|other', path: 'optional', url: 'optional', sourceTool: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
293
292
|
decisionsAppend: [{ summary: 'decision', rationale: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
294
293
|
blockersUpsert: [{ summary: 'blocker', kind: 'approval|credential|human_input|external_dependency|error|other', nextAction: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
@@ -298,21 +297,6 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
298
297
|
}),
|
|
299
298
|
'',
|
|
300
299
|
`source: ${JSON.stringify(cleanText(input.source, 80) || 'chat')}`,
|
|
301
|
-
`mission: ${JSON.stringify(input.mission ? {
|
|
302
|
-
id: input.mission.id,
|
|
303
|
-
objective: cleanMultiline(input.mission.objective, 600),
|
|
304
|
-
status: input.mission.status,
|
|
305
|
-
phase: input.mission.phase,
|
|
306
|
-
currentStep: cleanText(input.mission.currentStep, 240) || null,
|
|
307
|
-
plannerSummary: cleanText(input.mission.plannerSummary, 280) || null,
|
|
308
|
-
verifierSummary: cleanText(input.mission.verifierSummary, 280) || null,
|
|
309
|
-
blockerSummary: cleanText(input.mission.blockerSummary, 240) || null,
|
|
310
|
-
waitState: input.mission.waitState ? {
|
|
311
|
-
kind: input.mission.waitState.kind,
|
|
312
|
-
reason: cleanText(input.mission.waitState.reason, 240),
|
|
313
|
-
approvalId: cleanText(input.mission.waitState.approvalId, 120) || null,
|
|
314
|
-
} : null,
|
|
315
|
-
} : null)}`,
|
|
316
300
|
`current_state:\n${renderStateForExtraction(input.currentState)}`,
|
|
317
301
|
`user_message: ${JSON.stringify(cleanMultiline(input.message, 1200) || null)}`,
|
|
318
302
|
`assistant_text: ${JSON.stringify(cleanMultiline(input.assistantText, 1200) || null)}`,
|
|
@@ -398,7 +382,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
398
382
|
value: input.runId,
|
|
399
383
|
runId: input.runId,
|
|
400
384
|
sessionId: input.sessionId,
|
|
401
|
-
missionId: input.mission?.id || null,
|
|
402
385
|
createdAt: nowTs,
|
|
403
386
|
})
|
|
404
387
|
}
|
|
@@ -420,7 +403,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
420
403
|
toolCallId: cleanText(event.toolCallId, 120) || null,
|
|
421
404
|
runId: input.runId || null,
|
|
422
405
|
sessionId: input.sessionId,
|
|
423
|
-
missionId: input.mission?.id || null,
|
|
424
406
|
createdAt: nowTs + index,
|
|
425
407
|
})
|
|
426
408
|
|
|
@@ -428,7 +410,7 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
428
410
|
blockersUpsert.push({
|
|
429
411
|
summary: output || `Tool ${toolName} failed.`,
|
|
430
412
|
kind: 'error',
|
|
431
|
-
nextAction:
|
|
413
|
+
nextAction: null,
|
|
432
414
|
status: 'active',
|
|
433
415
|
evidenceIds: [evidenceId],
|
|
434
416
|
})
|
|
@@ -521,7 +503,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
521
503
|
value: cleanText(input.error, 240) || null,
|
|
522
504
|
runId: input.runId || null,
|
|
523
505
|
sessionId: input.sessionId,
|
|
524
|
-
missionId: input.mission?.id || null,
|
|
525
506
|
createdAt: nowTs + 100,
|
|
526
507
|
})
|
|
527
508
|
blockersUpsert.push({
|
|
@@ -531,26 +512,11 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
531
512
|
})
|
|
532
513
|
}
|
|
533
514
|
|
|
534
|
-
if (input.mission) {
|
|
535
|
-
evidenceAppend.push({
|
|
536
|
-
id: genId(12),
|
|
537
|
-
type: 'mission',
|
|
538
|
-
summary: `Mission state updated: ${input.mission.status}/${input.mission.phase}.`,
|
|
539
|
-
value: cleanText(input.mission.currentStep || input.mission.objective, 240) || null,
|
|
540
|
-
runId: input.runId || null,
|
|
541
|
-
sessionId: input.sessionId,
|
|
542
|
-
missionId: input.mission.id,
|
|
543
|
-
createdAt: nowTs + 200,
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
|
|
547
515
|
return {
|
|
548
516
|
status: input.error
|
|
549
517
|
? 'blocked'
|
|
550
|
-
:
|
|
551
|
-
|
|
552
|
-
: undefined,
|
|
553
|
-
nextAction: cleanText(input.mission?.currentStep, 240) || undefined,
|
|
518
|
+
: undefined,
|
|
519
|
+
nextAction: undefined,
|
|
554
520
|
factsUpsert: factsUpsert.length > 0 ? factsUpsert : undefined,
|
|
555
521
|
artifactsUpsert: artifactsUpsert.length > 0 ? artifactsUpsert : undefined,
|
|
556
522
|
blockersUpsert: blockersUpsert.length > 0 ? blockersUpsert : undefined,
|
|
@@ -608,7 +574,7 @@ export function shouldExtractStructuredPatch(input: SynchronizeWorkingStateForTu
|
|
|
608
574
|
const hasAssistantText = cleanMultiline(input.assistantText, 400).length > 0
|
|
609
575
|
const hasError = cleanText(input.error, 120).length > 0
|
|
610
576
|
if (cleanText(input.source, 80) === 'heartbeat') {
|
|
611
|
-
return hasToolEvents || hasError
|
|
577
|
+
return hasToolEvents || hasError
|
|
612
578
|
}
|
|
613
|
-
return hasToolEvents || hasAssistantText || hasMessage || hasError
|
|
579
|
+
return hasToolEvents || hasAssistantText || hasMessage || hasError
|
|
614
580
|
}
|