@swarmclawai/swarmclaw 1.2.8 → 1.3.0

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.
Files changed (214) hide show
  1. package/README.md +39 -6
  2. package/package.json +2 -2
  3. package/src/app/agents/[id]/page.tsx +1 -18
  4. package/src/app/api/activity/route.ts +9 -23
  5. package/src/app/api/agents/route.ts +17 -1
  6. package/src/app/api/agents/thread-route.test.ts +0 -1
  7. package/src/app/api/approvals/route.test.ts +6 -22
  8. package/src/app/api/approvals/route.ts +13 -5
  9. package/src/app/api/connectors/route.ts +2 -2
  10. package/src/app/api/credentials/[id]/route.ts +2 -0
  11. package/src/app/api/credentials/route.ts +4 -1
  12. package/src/app/api/goals/[id]/route.ts +28 -0
  13. package/src/app/api/goals/route.ts +33 -0
  14. package/src/app/api/portability/export/route.ts +8 -0
  15. package/src/app/api/portability/import/route.test.ts +80 -0
  16. package/src/app/api/portability/import/route.ts +28 -0
  17. package/src/app/api/protocols/templates/[id]/route.ts +2 -1
  18. package/src/app/api/protocols/templates/route.ts +2 -1
  19. package/src/app/api/settings/route.ts +13 -2
  20. package/src/app/api/wallets/[id]/route.ts +15 -157
  21. package/src/app/api/wallets/generate/route.ts +22 -0
  22. package/src/app/api/wallets/route.test.ts +147 -0
  23. package/src/app/api/wallets/route.ts +13 -95
  24. package/src/app/autonomy/page.tsx +2 -57
  25. package/src/app/home/page.tsx +3 -0
  26. package/src/app/protocols/page.tsx +2 -21
  27. package/src/app/settings/page.tsx +0 -9
  28. package/src/app/wallets/page.tsx +105 -5
  29. package/src/cli/index.js +32 -33
  30. package/src/cli/spec.js +26 -27
  31. package/src/components/agents/agent-sheet.tsx +2 -40
  32. package/src/components/agents/inspector-panel.tsx +0 -83
  33. package/src/components/chat/chat-card.tsx +0 -31
  34. package/src/components/chat/message-bubble.tsx +1 -108
  35. package/src/components/connectors/connector-sheet.tsx +25 -1
  36. package/src/components/layout/sidebar-rail.tsx +6 -10
  37. package/src/components/projects/project-detail.tsx +3 -35
  38. package/src/components/projects/tabs/overview-tab.tsx +3 -59
  39. package/src/components/projects/tabs/work-tab.tsx +7 -77
  40. package/src/components/protocols/structured-session-launcher.tsx +1 -22
  41. package/src/components/shared/connector-platform-icon.tsx +1 -0
  42. package/src/components/tasks/task-card.tsx +4 -34
  43. package/src/components/tasks/task-sheet.tsx +6 -36
  44. package/src/components/wallets/wallet-list.tsx +150 -0
  45. package/src/lib/app/navigation.test.ts +0 -13
  46. package/src/lib/app/navigation.ts +2 -7
  47. package/src/lib/app/view-constants.ts +14 -19
  48. package/src/lib/server/activity/activity-log.ts +16 -1
  49. package/src/lib/server/agents/agent-service.ts +24 -11
  50. package/src/lib/server/agents/agent-thread-session.ts +0 -1
  51. package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
  52. package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
  53. package/src/lib/server/agents/delegation-jobs.ts +0 -25
  54. package/src/lib/server/agents/main-agent-loop.ts +1 -49
  55. package/src/lib/server/agents/subagent-runtime.ts +0 -1
  56. package/src/lib/server/approval-match.ts +14 -85
  57. package/src/lib/server/approvals/approval-hooks.ts +81 -0
  58. package/src/lib/server/approvals.test.ts +6 -6
  59. package/src/lib/server/approvals.ts +11 -6
  60. package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
  61. package/src/lib/server/builtin-extensions.ts +0 -2
  62. package/src/lib/server/capability-router.test.ts +0 -2
  63. package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
  64. package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
  65. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
  66. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
  67. package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
  68. package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
  69. package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
  70. package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
  71. package/src/lib/server/chat-execution/message-classifier.ts +1 -16
  72. package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
  73. package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
  74. package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
  75. package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
  76. package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
  77. package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
  78. package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
  79. package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
  80. package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
  81. package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
  82. package/src/lib/server/chats/chat-session-service.ts +3 -5
  83. package/src/lib/server/connectors/connector-inbound.ts +0 -1
  84. package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
  85. package/src/lib/server/connectors/connector-service.ts +39 -9
  86. package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
  87. package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
  88. package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
  89. package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
  90. package/src/lib/server/connectors/swarmdock-tasks.ts +127 -0
  91. package/src/lib/server/connectors/swarmdock.ts +285 -0
  92. package/src/lib/server/execution-brief.test.ts +2 -25
  93. package/src/lib/server/execution-brief.ts +30 -35
  94. package/src/lib/server/execution-engine/task-attempt.ts +0 -1
  95. package/src/lib/server/goals/goal-repository.ts +19 -0
  96. package/src/lib/server/goals/goal-service.ts +143 -0
  97. package/src/lib/server/persistence/storage-context.ts +0 -5
  98. package/src/lib/server/portability/export.ts +109 -0
  99. package/src/lib/server/portability/import.ts +159 -0
  100. package/src/lib/server/protocols/protocol-normalization.ts +0 -4
  101. package/src/lib/server/protocols/protocol-queries.ts +0 -6
  102. package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
  103. package/src/lib/server/protocols/protocol-service.ts +0 -1
  104. package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
  105. package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
  106. package/src/lib/server/protocols/protocol-swarm.ts +0 -2
  107. package/src/lib/server/protocols/protocol-types.ts +0 -2
  108. package/src/lib/server/provider-health.ts +0 -9
  109. package/src/lib/server/runtime/daemon-state/core.ts +0 -9
  110. package/src/lib/server/runtime/daemon-state.test.ts +0 -35
  111. package/src/lib/server/runtime/heartbeat-service.ts +3 -23
  112. package/src/lib/server/runtime/queue/core.ts +11 -33
  113. package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
  114. package/src/lib/server/runtime/scheduler.ts +0 -13
  115. package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
  116. package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
  117. package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
  118. package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
  119. package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
  120. package/src/lib/server/session-tools/crud.ts +0 -14
  121. package/src/lib/server/session-tools/delegate.ts +0 -4
  122. package/src/lib/server/session-tools/index.ts +0 -4
  123. package/src/lib/server/session-tools/team-context.ts +0 -3
  124. package/src/lib/server/storage-normalization.ts +13 -0
  125. package/src/lib/server/storage.ts +75 -45
  126. package/src/lib/server/tasks/task-checkout.ts +59 -0
  127. package/src/lib/server/tasks/task-lifecycle.ts +2 -0
  128. package/src/lib/server/tasks/task-route-service.ts +4 -26
  129. package/src/lib/server/tasks/task-service.ts +0 -7
  130. package/src/lib/server/tool-aliases.ts +0 -1
  131. package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
  132. package/src/lib/server/tool-capability-policy.ts +0 -2
  133. package/src/lib/server/tool-planning.ts +0 -12
  134. package/src/lib/server/universal-tool-access.ts +0 -1
  135. package/src/lib/server/usage/cost-rollup.ts +124 -0
  136. package/src/lib/server/usage/usage-repository.ts +6 -0
  137. package/src/lib/server/wallets/wallet-crypto.ts +33 -0
  138. package/src/lib/server/wallets/wallet-repository.ts +24 -0
  139. package/src/lib/server/wallets/wallet-service.ts +119 -0
  140. package/src/lib/server/working-state/extraction.ts +8 -42
  141. package/src/lib/server/working-state/normalization.ts +10 -103
  142. package/src/lib/server/working-state/service.ts +12 -21
  143. package/src/lib/strip-internal-metadata.test.ts +1 -1
  144. package/src/lib/strip-internal-metadata.ts +1 -1
  145. package/src/lib/tool-definitions.ts +0 -1
  146. package/src/lib/validation/schemas.ts +36 -32
  147. package/src/lib/validation/server-schemas.ts +35 -0
  148. package/src/stores/slices/data-slice.ts +5 -1
  149. package/src/stores/slices/ui-slice.ts +0 -4
  150. package/src/types/agent.ts +10 -84
  151. package/src/types/app-settings.ts +6 -2
  152. package/src/types/approval.ts +3 -2
  153. package/src/types/connector.ts +1 -0
  154. package/src/types/goal.ts +30 -0
  155. package/src/types/index.ts +2 -1
  156. package/src/types/message.ts +0 -1
  157. package/src/types/misc.ts +2 -4
  158. package/src/types/protocol.ts +0 -2
  159. package/src/types/run.ts +0 -3
  160. package/src/types/session.ts +1 -51
  161. package/src/types/swarmdock.ts +29 -0
  162. package/src/types/task.ts +9 -3
  163. package/src/types/working-state.ts +2 -9
  164. package/src/views/settings/section-runtime-loop.tsx +0 -14
  165. package/src/app/api/canvas/[sessionId]/route.ts +0 -35
  166. package/src/app/api/missions/[id]/actions/route.ts +0 -31
  167. package/src/app/api/missions/[id]/events/route.ts +0 -14
  168. package/src/app/api/missions/[id]/route.ts +0 -10
  169. package/src/app/api/missions/route.test.ts +0 -244
  170. package/src/app/api/missions/route.ts +0 -57
  171. package/src/app/api/wallets/[id]/approve/route.ts +0 -79
  172. package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
  173. package/src/app/api/wallets/[id]/send/route.ts +0 -113
  174. package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
  175. package/src/app/missions/[id]/page.tsx +0 -3
  176. package/src/app/missions/page.tsx +0 -685
  177. package/src/components/canvas/canvas-panel.tsx +0 -267
  178. package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
  179. package/src/components/wallets/wallet-panel.tsx +0 -1010
  180. package/src/components/wallets/wallet-section.tsx +0 -260
  181. package/src/features/missions/queries.ts +0 -23
  182. package/src/lib/canvas-content.test.ts +0 -360
  183. package/src/lib/canvas-content.ts +0 -198
  184. package/src/lib/server/canvas-content.test.ts +0 -32
  185. package/src/lib/server/canvas-content.ts +0 -6
  186. package/src/lib/server/ethereum.ts +0 -591
  187. package/src/lib/server/evm-swap.ts +0 -476
  188. package/src/lib/server/missions/mission-intent.test.ts +0 -63
  189. package/src/lib/server/missions/mission-intent.ts +0 -569
  190. package/src/lib/server/missions/mission-repository.ts +0 -74
  191. package/src/lib/server/missions/mission-service/actions.ts +0 -6
  192. package/src/lib/server/missions/mission-service/bindings.ts +0 -9
  193. package/src/lib/server/missions/mission-service/context.ts +0 -4
  194. package/src/lib/server/missions/mission-service/core.ts +0 -2271
  195. package/src/lib/server/missions/mission-service/queries.ts +0 -12
  196. package/src/lib/server/missions/mission-service/recovery.ts +0 -5
  197. package/src/lib/server/missions/mission-service/ticks.ts +0 -9
  198. package/src/lib/server/missions/mission-service.test.ts +0 -888
  199. package/src/lib/server/missions/mission-service.ts +0 -6
  200. package/src/lib/server/session-tools/canvas.ts +0 -105
  201. package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
  202. package/src/lib/server/session-tools/wallet.ts +0 -1287
  203. package/src/lib/server/solana.ts +0 -327
  204. package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
  205. package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
  206. package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
  207. package/src/lib/server/wallet/wallet-service.test.ts +0 -81
  208. package/src/lib/server/wallet/wallet-service.ts +0 -225
  209. package/src/lib/wallet/wallet-transactions.test.ts +0 -75
  210. package/src/lib/wallet/wallet-transactions.ts +0 -43
  211. package/src/lib/wallet/wallet.test.ts +0 -333
  212. package/src/lib/wallet/wallet.ts +0 -183
  213. package/src/types/mission.ts +0 -185
  214. package/src/views/settings/section-wallets.tsx +0 -35
@@ -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, tool results, and mission snapshot.',
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, mission state, or tool evidence. Do not turn guesses into facts.',
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|mission|system', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
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: cleanText(input.mission?.currentStep, 240) || null,
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
- : input.mission
551
- ? missionStatusToWorkingStateStatus(input.mission)
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 || Boolean(input.mission)
577
+ return hasToolEvents || hasError
612
578
  }
613
- return hasToolEvents || hasAssistantText || hasMessage || hasError || Boolean(input.mission)
579
+ return hasToolEvents || hasAssistantText || hasMessage || hasError
614
580
  }
@@ -4,7 +4,6 @@ import { genId } from '@/lib/id'
4
4
  import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
5
5
  import type {
6
6
  EvidenceRef,
7
- Mission,
8
7
  SessionWorkingState,
9
8
  WorkingArtifact,
10
9
  WorkingArtifactPatch,
@@ -56,7 +55,7 @@ export const WorkingPlanStepPatchSchema = z.object({
56
55
  export const WorkingFactPatchSchema = z.object({
57
56
  id: z.string().optional().nullable(),
58
57
  statement: z.string().optional().nullable(),
59
- source: z.enum(['user', 'tool', 'assistant', 'mission', 'system']).optional().nullable(),
58
+ source: z.enum(['user', 'tool', 'assistant', 'system']).optional().nullable(),
60
59
  status: WorkingItemStatusSchema.optional().nullable(),
61
60
  evidenceIds: z.array(z.string()).optional().nullable(),
62
61
  })
@@ -150,7 +149,6 @@ import type { MessageToolEvent } from '@/types'
150
149
 
151
150
  export interface WorkingStateDeterministicUpdateInput {
152
151
  sessionId: string
153
- mission?: Mission | null
154
152
  message?: string | null
155
153
  assistantText?: string | null
156
154
  error?: string | null
@@ -233,7 +231,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
233
231
  if (!summary) return null
234
232
  const type = record.type === 'tool'
235
233
  || record.type === 'message'
236
- || record.type === 'mission'
237
234
  || record.type === 'task'
238
235
  || record.type === 'artifact'
239
236
  || record.type === 'error'
@@ -249,7 +246,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
249
246
  toolCallId: cleanText(record.toolCallId, 120) || null,
250
247
  runId: cleanText(record.runId, 120) || null,
251
248
  sessionId: cleanText(record.sessionId, 120) || null,
252
- missionId: cleanText(record.missionId, 120) || null,
253
249
  taskId: cleanText(record.taskId, 120) || null,
254
250
  createdAt: typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
255
251
  ? Math.trunc(record.createdAt)
@@ -290,7 +286,6 @@ export function normalizeFact(input: unknown): WorkingFact | null {
290
286
  source: record.source === 'user'
291
287
  || record.source === 'tool'
292
288
  || record.source === 'assistant'
293
- || record.source === 'mission'
294
289
  || record.source === 'system'
295
290
  ? record.source
296
291
  : 'assistant',
@@ -434,17 +429,16 @@ export function normalizeMatchKey(value: string): string {
434
429
  // defaultWorkingState & normalizeWorkingState
435
430
  // ---------------------------------------------------------------------------
436
431
 
437
- export function defaultWorkingState(sessionId: string, mission?: Mission | null): SessionWorkingState {
432
+ export function defaultWorkingState(sessionId: string): SessionWorkingState {
438
433
  const nowTs = now()
439
434
  return {
440
435
  sessionId,
441
- missionId: mission?.id || null,
442
- objective: cleanMultiline(mission?.objective, 900) || null,
443
- summary: cleanMultiline(mission?.verifierSummary || mission?.plannerSummary, 600) || null,
436
+ objective: null,
437
+ summary: null,
444
438
  constraints: [],
445
- successCriteria: normalizeList(mission?.successCriteria, 12, 240),
446
- status: mission ? missionStatusToWorkingStateStatus(mission) : 'idle',
447
- nextAction: cleanText(mission?.currentStep, 240) || null,
439
+ successCriteria: [],
440
+ status: 'idle',
441
+ nextAction: null,
448
442
  planSteps: [],
449
443
  confirmedFacts: [],
450
444
  artifacts: [],
@@ -462,19 +456,17 @@ export function defaultWorkingState(sessionId: string, mission?: Mission | null)
462
456
  export function normalizeWorkingState(
463
457
  input: unknown,
464
458
  sessionId: string,
465
- mission?: Mission | null,
466
459
  ): SessionWorkingState {
467
460
  if (!input || typeof input !== 'object' || Array.isArray(input)) {
468
- return defaultWorkingState(sessionId, mission)
461
+ return defaultWorkingState(sessionId)
469
462
  }
470
463
  const record = input as Record<string, unknown>
471
- const base = defaultWorkingState(sessionId, mission)
464
+ const base = defaultWorkingState(sessionId)
472
465
  const createdAt = typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
473
466
  ? Math.trunc(record.createdAt)
474
467
  : base.createdAt
475
468
  const normalized: SessionWorkingState = {
476
469
  sessionId: cleanText(record.sessionId, 120) || sessionId,
477
- missionId: cleanText(record.missionId, 120) || mission?.id || null,
478
470
  objective: cleanMultiline(record.objective, 900) || base.objective,
479
471
  summary: cleanMultiline(record.summary, 600) || base.summary,
480
472
  constraints: normalizeList(record.constraints, 12, 240),
@@ -497,7 +489,7 @@ export function normalizeWorkingState(
497
489
  ? Math.trunc(record.lastCompactedAt)
498
490
  : null,
499
491
  }
500
- return compactWorkingStateObject(syncWorkingStateWithMission(normalized, mission))
492
+ return compactWorkingStateObject(normalized)
501
493
  }
502
494
 
503
495
  // ---------------------------------------------------------------------------
@@ -522,89 +514,6 @@ export function compactWorkingStateObject(state: SessionWorkingState): SessionWo
522
514
  }
523
515
 
524
516
  // ---------------------------------------------------------------------------
525
- // missionStatusToWorkingStateStatus & syncWorkingStateWithMission
526
- // ---------------------------------------------------------------------------
527
-
528
- export function missionStatusToWorkingStateStatus(mission: Mission): WorkingStateStatus {
529
- if (mission.status === 'completed') return 'completed'
530
- if (mission.status === 'waiting') return 'waiting'
531
- if (mission.status === 'failed' || mission.status === 'cancelled') return 'blocked'
532
- return 'progress'
533
- }
534
-
535
- export function syncWorkingStateWithMission(
536
- state: SessionWorkingState,
537
- mission?: Mission | null,
538
- ): SessionWorkingState {
539
- if (!mission) return state
540
- const next = { ...state }
541
- next.missionId = mission.id
542
- next.objective = cleanMultiline(mission.objective, 900) || next.objective
543
- next.successCriteria = normalizeList(mission.successCriteria, 12, 240)
544
- next.summary = next.summary || cleanMultiline(mission.verifierSummary || mission.plannerSummary, 600) || null
545
- const missionStatus = missionStatusToWorkingStateStatus(mission)
546
- if (missionStatus === 'completed' || missionStatus === 'waiting' || missionStatus === 'blocked') {
547
- next.status = missionStatus
548
- } else if (next.status === 'idle') {
549
- next.status = missionStatus
550
- }
551
- next.nextAction = next.nextAction || cleanText(mission.currentStep, 240) || null
552
-
553
- if (mission.currentStep) {
554
- next.planSteps = upsertItems(next.planSteps, [{
555
- id: null,
556
- text: mission.currentStep,
557
- status: mission.status === 'completed' ? 'resolved' : 'active',
558
- } satisfies WorkingPlanStepPatch], {
559
- max: MAX_PLAN_STEPS,
560
- getPatchId: (patch) => cleanText(patch.id, 120) || null,
561
- getPatchKey: (patch) => cleanText(patch.text, 240),
562
- getItemKey: (item) => item.text,
563
- create: (patch, nowTs) => ({
564
- id: genId(12),
565
- text: cleanText(patch.text, 240),
566
- status: normalizeItemStatus(patch.status),
567
- createdAt: nowTs,
568
- updatedAt: nowTs,
569
- }),
570
- merge: (current, patch, nowTs) => ({
571
- ...current,
572
- text: cleanText(patch.text, 240) || current.text,
573
- status: normalizeItemStatus(patch.status, current.status),
574
- updatedAt: nowTs,
575
- }),
576
- compact: compactPlanSteps,
577
- })
578
- }
579
-
580
- if (mission.waitState?.reason || mission.blockerSummary) {
581
- const blockerSummary = cleanText(mission.waitState?.reason || mission.blockerSummary, 280)
582
- if (blockerSummary) {
583
- next.blockers = upsertItems(next.blockers, [{
584
- summary: blockerSummary,
585
- kind: mission.waitState?.kind === 'approval'
586
- ? 'approval'
587
- : mission.waitState?.kind === 'human_reply'
588
- ? 'human_input'
589
- : mission.waitState?.kind === 'external_dependency' || mission.waitState?.kind === 'provider'
590
- ? 'external_dependency'
591
- : mission.status === 'failed'
592
- ? 'error'
593
- : 'other',
594
- nextAction: mission.currentStep || null,
595
- status: mission.status === 'completed' ? 'resolved' : 'active',
596
- }], blockerUpsertConfig())
597
- }
598
- }
599
-
600
- if (mission.status === 'completed') {
601
- next.blockers = next.blockers.map((blocker) => blocker.status === 'active'
602
- ? { ...blocker, status: 'resolved', updatedAt: now() }
603
- : blocker)
604
- }
605
-
606
- return next
607
- }
608
517
 
609
518
  // ---------------------------------------------------------------------------
610
519
  // upsertItems & upsertConfig factories
@@ -647,7 +556,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
647
556
  source: patch.source === 'user'
648
557
  || patch.source === 'tool'
649
558
  || patch.source === 'assistant'
650
- || patch.source === 'mission'
651
559
  || patch.source === 'system'
652
560
  ? patch.source
653
561
  : 'assistant',
@@ -662,7 +570,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
662
570
  source: patch.source === 'user'
663
571
  || patch.source === 'tool'
664
572
  || patch.source === 'assistant'
665
- || patch.source === 'mission'
666
573
  || patch.source === 'system'
667
574
  ? patch.source
668
575
  : current.source,
@@ -1,7 +1,6 @@
1
1
  import { genId } from '@/lib/id'
2
2
  import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
3
3
  import type {
4
- Mission,
5
4
  SessionWorkingState,
6
5
  WorkingBlocker,
7
6
  WorkingPlanStepPatch,
@@ -20,7 +19,6 @@ import {
20
19
  normalizeWorkingState,
21
20
  defaultWorkingState,
22
21
  compactWorkingStateObject,
23
- syncWorkingStateWithMission,
24
22
  normalizeItemStatus,
25
23
  normalizeStateStatus,
26
24
  upsertItems,
@@ -96,8 +94,6 @@ export {
96
94
  compactPlanSteps,
97
95
  defaultWorkingState,
98
96
  compactWorkingStateObject,
99
- missionStatusToWorkingStateStatus,
100
- syncWorkingStateWithMission,
101
97
  // Upsert
102
98
  upsertItems,
103
99
  factUpsertConfig,
@@ -142,14 +138,14 @@ export { buildWorkingStatePromptBlockFromState } from '@/lib/server/working-stat
142
138
  // CRUD / coordination layer
143
139
  // ---------------------------------------------------------------------------
144
140
 
145
- export function loadSessionWorkingState(sessionId: string, options?: { mission?: Mission | null }): SessionWorkingState | null {
141
+ export function loadSessionWorkingState(sessionId: string): SessionWorkingState | null {
146
142
  const stored = loadPersistedWorkingState(sessionId)
147
- if (!stored && !options?.mission) return null
148
- return normalizeWorkingState(stored, sessionId, options?.mission || null)
143
+ if (!stored) return null
144
+ return normalizeWorkingState(stored, sessionId)
149
145
  }
150
146
 
151
- export function getOrCreateSessionWorkingState(sessionId: string, options?: { mission?: Mission | null }): SessionWorkingState {
152
- return loadSessionWorkingState(sessionId, options) || defaultWorkingState(sessionId, options?.mission || null)
147
+ export function getOrCreateSessionWorkingState(sessionId: string): SessionWorkingState {
148
+ return loadSessionWorkingState(sessionId) || defaultWorkingState(sessionId)
153
149
  }
154
150
 
155
151
  export function saveSessionWorkingState(state: SessionWorkingState): SessionWorkingState {
@@ -165,12 +161,10 @@ export function deleteSessionWorkingState(sessionId: string): void {
165
161
  export function applyWorkingStatePatch(
166
162
  sessionId: string,
167
163
  patch: WorkingStatePatch,
168
- options?: { mission?: Mission | null },
169
164
  ): SessionWorkingState {
170
- const current = getOrCreateSessionWorkingState(sessionId, options)
165
+ const current = getOrCreateSessionWorkingState(sessionId)
171
166
  const next: SessionWorkingState = {
172
167
  ...current,
173
- missionId: options?.mission?.id || current.missionId || null,
174
168
  objective: patch.objective !== undefined ? (cleanMultiline(patch.objective, 900) || null) : current.objective,
175
169
  summary: patch.summary !== undefined ? (cleanMultiline(patch.summary, 600) || null) : current.summary,
176
170
  constraints: patch.constraints !== undefined ? normalizeList(patch.constraints, 12, 240) : current.constraints,
@@ -215,16 +209,15 @@ export function applyWorkingStatePatch(
215
209
  next.openQuestions = markSuperseded(next.openQuestions, patch.supersedeIds)
216
210
  next.hypotheses = markSuperseded(next.hypotheses, patch.supersedeIds)
217
211
 
218
- const synced = compactWorkingStateObject(syncWorkingStateWithMission(next, options?.mission || null))
219
- upsertPersistedWorkingState(sessionId, synced as unknown as Record<string, unknown>)
220
- return synced
212
+ const compacted = compactWorkingStateObject(next)
213
+ upsertPersistedWorkingState(sessionId, compacted as unknown as Record<string, unknown>)
214
+ return compacted
221
215
  }
222
216
 
223
217
  export function recordWorkingStateEvidence(input: WorkingStateDeterministicUpdateInput): SessionWorkingState {
224
218
  return applyWorkingStatePatch(
225
219
  input.sessionId,
226
220
  deterministicEvidencePatch(input),
227
- { mission: input.mission || null },
228
221
  )
229
222
  }
230
223
 
@@ -241,12 +234,11 @@ export async function synchronizeWorkingStateForTurn(
241
234
  currentState: deterministic,
242
235
  }, options)
243
236
  if (!patch) return deterministic
244
- return applyWorkingStatePatch(input.sessionId, patch, { mission: input.mission || null })
237
+ return applyWorkingStatePatch(input.sessionId, patch)
245
238
  }
246
239
 
247
240
  export function syncWorkingStateFromMainLoopState(input: {
248
241
  sessionId: string
249
- mission?: Mission | null
250
242
  goal?: string | null
251
243
  summary?: string | null
252
244
  status?: WorkingStateStatus | null
@@ -281,13 +273,12 @@ export function syncWorkingStateFromMainLoopState(input: {
281
273
  status: (input.status === 'completed' ? 'resolved' : 'active') as WorkingStateItemStatus,
282
274
  })).filter((fact) => fact.statement)
283
275
  : undefined,
284
- }, { mission: input.mission || null })
276
+ })
285
277
  }
286
278
 
287
279
  export function buildWorkingStatePromptBlock(
288
280
  sessionId: string,
289
- options?: { mission?: Mission | null },
290
281
  ): string {
291
- const state = loadSessionWorkingState(sessionId, options)
282
+ const state = loadSessionWorkingState(sessionId)
292
283
  return buildWorkingStatePromptBlockFromState(state)
293
284
  }
@@ -31,7 +31,7 @@ describe('stripInternalJson', () => {
31
31
  })
32
32
 
33
33
  it('removes JSON with nested objects when internal keys are present', () => {
34
- const input = '{ "walletIntent": "send", "details": { "amount": 100 } }'
34
+ const input = '{ "isDeliverableTask": true, "details": { "amount": 100 } }'
35
35
  assert.equal(stripInternalJson(input).trim(), '')
36
36
  })
37
37
 
@@ -15,7 +15,7 @@
15
15
  // ---------------------------------------------------------------------------
16
16
 
17
17
  const INTERNAL_JSON_KEYS = [
18
- 'isDeliverableTask', 'quality_score', 'isBroadGoal', 'walletIntent',
18
+ 'isDeliverableTask', 'quality_score', 'isBroadGoal',
19
19
  'hasHumanSignals', 'explicitToolRequests', 'isResearchSynthesis', 'confidence',
20
20
  ]
21
21
 
@@ -23,7 +23,6 @@ export const AVAILABLE_TOOLS: ToolDefinition[] = [
23
23
  { id: 'delegate', label: 'Delegate', description: 'Delegate complex tasks to specialized backends (Claude Code, Codex, OpenCode)' },
24
24
  { id: 'browser', label: 'Browser', description: 'Playwright — browse, scrape, interact with web pages' },
25
25
  { id: 'memory', label: 'Memory', description: 'Store and retrieve long-term memories across conversations' },
26
- { id: 'wallet', label: 'Wallet', description: 'Manage agent crypto wallet — check balance, send SOL, view transactions', extensionId: 'wallet' },
27
26
  { id: 'monitor', label: 'Monitor', description: 'Durable watch jobs: monitor files, endpoints, tasks, and resume agents on triggers' },
28
27
  { id: 'extension_creator', label: 'Extension Creator', description: 'Design focused extensions for durable capabilities and recurring automations' },
29
28
  { id: 'image_gen', label: 'Image Generation', description: 'Generate images from text prompts using OpenAI, Stability AI, Replicate, fal.ai, and more', extensionId: 'image_gen' },