@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.
Files changed (195) hide show
  1. package/README.md +30 -6
  2. package/package.json +2 -2
  3. package/src/app/agents/[id]/page.tsx +1 -18
  4. package/src/app/api/agents/thread-route.test.ts +0 -1
  5. package/src/app/api/approvals/route.test.ts +6 -22
  6. package/src/app/api/connectors/route.ts +2 -2
  7. package/src/app/api/portability/export/route.ts +8 -0
  8. package/src/app/api/portability/import/route.test.ts +80 -0
  9. package/src/app/api/portability/import/route.ts +28 -0
  10. package/src/app/api/settings/route.ts +0 -2
  11. package/src/app/api/wallets/[id]/route.ts +15 -157
  12. package/src/app/api/wallets/generate/route.ts +22 -0
  13. package/src/app/api/wallets/route.test.ts +147 -0
  14. package/src/app/api/wallets/route.ts +13 -95
  15. package/src/app/autonomy/page.tsx +2 -57
  16. package/src/app/protocols/page.tsx +2 -21
  17. package/src/app/settings/page.tsx +0 -9
  18. package/src/app/wallets/page.tsx +105 -5
  19. package/src/cli/index.js +21 -33
  20. package/src/cli/spec.js +19 -30
  21. package/src/components/agents/agent-sheet.tsx +2 -40
  22. package/src/components/agents/inspector-panel.tsx +0 -83
  23. package/src/components/chat/chat-card.tsx +0 -31
  24. package/src/components/chat/message-bubble.tsx +1 -108
  25. package/src/components/connectors/connector-sheet.tsx +25 -1
  26. package/src/components/layout/sidebar-rail.tsx +6 -10
  27. package/src/components/projects/project-detail.tsx +3 -35
  28. package/src/components/projects/tabs/overview-tab.tsx +3 -59
  29. package/src/components/projects/tabs/work-tab.tsx +7 -77
  30. package/src/components/protocols/structured-session-launcher.tsx +1 -22
  31. package/src/components/shared/connector-platform-icon.tsx +1 -0
  32. package/src/components/tasks/task-card.tsx +4 -34
  33. package/src/components/tasks/task-sheet.tsx +6 -36
  34. package/src/components/wallets/wallet-list.tsx +150 -0
  35. package/src/lib/app/navigation.test.ts +0 -13
  36. package/src/lib/app/navigation.ts +2 -7
  37. package/src/lib/app/view-constants.ts +14 -19
  38. package/src/lib/server/agents/agent-thread-session.ts +0 -1
  39. package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
  40. package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
  41. package/src/lib/server/agents/delegation-jobs.ts +0 -25
  42. package/src/lib/server/agents/main-agent-loop.ts +1 -49
  43. package/src/lib/server/agents/subagent-runtime.ts +0 -1
  44. package/src/lib/server/approval-match.ts +0 -85
  45. package/src/lib/server/approvals.test.ts +6 -6
  46. package/src/lib/server/approvals.ts +0 -6
  47. package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
  48. package/src/lib/server/builtin-extensions.ts +0 -2
  49. package/src/lib/server/capability-router.test.ts +0 -2
  50. package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
  51. package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
  52. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
  53. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
  54. package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
  55. package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
  56. package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
  57. package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
  58. package/src/lib/server/chat-execution/message-classifier.ts +1 -16
  59. package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
  60. package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
  61. package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
  62. package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
  63. package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
  64. package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
  65. package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
  66. package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
  67. package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
  68. package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
  69. package/src/lib/server/chats/chat-session-service.ts +3 -5
  70. package/src/lib/server/connectors/connector-inbound.ts +0 -1
  71. package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
  72. package/src/lib/server/connectors/connector-service.ts +39 -9
  73. package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
  74. package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
  75. package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
  76. package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
  77. package/src/lib/server/connectors/swarmdock-tasks.ts +119 -0
  78. package/src/lib/server/connectors/swarmdock.ts +255 -0
  79. package/src/lib/server/execution-brief.test.ts +2 -25
  80. package/src/lib/server/execution-brief.ts +12 -35
  81. package/src/lib/server/execution-engine/task-attempt.ts +0 -1
  82. package/src/lib/server/persistence/storage-context.ts +0 -5
  83. package/src/lib/server/portability/export.ts +109 -0
  84. package/src/lib/server/portability/import.ts +159 -0
  85. package/src/lib/server/protocols/protocol-normalization.ts +0 -4
  86. package/src/lib/server/protocols/protocol-queries.ts +0 -6
  87. package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
  88. package/src/lib/server/protocols/protocol-service.ts +0 -1
  89. package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
  90. package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
  91. package/src/lib/server/protocols/protocol-swarm.ts +0 -2
  92. package/src/lib/server/protocols/protocol-types.ts +0 -2
  93. package/src/lib/server/provider-health.ts +0 -9
  94. package/src/lib/server/runtime/daemon-state/core.ts +0 -9
  95. package/src/lib/server/runtime/daemon-state.test.ts +0 -35
  96. package/src/lib/server/runtime/heartbeat-service.ts +3 -23
  97. package/src/lib/server/runtime/queue/core.ts +11 -33
  98. package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
  99. package/src/lib/server/runtime/scheduler.ts +0 -13
  100. package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
  101. package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
  102. package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
  103. package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
  104. package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
  105. package/src/lib/server/session-tools/crud.ts +0 -14
  106. package/src/lib/server/session-tools/delegate.ts +0 -4
  107. package/src/lib/server/session-tools/index.ts +0 -4
  108. package/src/lib/server/session-tools/team-context.ts +0 -3
  109. package/src/lib/server/storage-normalization.ts +8 -0
  110. package/src/lib/server/storage.ts +18 -45
  111. package/src/lib/server/tasks/task-checkout.ts +59 -0
  112. package/src/lib/server/tasks/task-lifecycle.ts +2 -0
  113. package/src/lib/server/tasks/task-route-service.ts +4 -26
  114. package/src/lib/server/tasks/task-service.ts +0 -7
  115. package/src/lib/server/tool-aliases.ts +0 -1
  116. package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
  117. package/src/lib/server/tool-capability-policy.ts +0 -2
  118. package/src/lib/server/tool-planning.ts +0 -12
  119. package/src/lib/server/universal-tool-access.ts +0 -1
  120. package/src/lib/server/wallets/wallet-crypto.ts +33 -0
  121. package/src/lib/server/wallets/wallet-repository.ts +24 -0
  122. package/src/lib/server/wallets/wallet-service.ts +119 -0
  123. package/src/lib/server/working-state/extraction.ts +8 -42
  124. package/src/lib/server/working-state/normalization.ts +10 -103
  125. package/src/lib/server/working-state/service.ts +12 -21
  126. package/src/lib/strip-internal-metadata.test.ts +1 -1
  127. package/src/lib/strip-internal-metadata.ts +1 -1
  128. package/src/lib/tool-definitions.ts +0 -1
  129. package/src/lib/validation/schemas.ts +33 -2
  130. package/src/stores/slices/data-slice.ts +5 -1
  131. package/src/stores/slices/ui-slice.ts +0 -4
  132. package/src/types/agent.ts +0 -84
  133. package/src/types/app-settings.ts +0 -2
  134. package/src/types/approval.ts +0 -2
  135. package/src/types/connector.ts +1 -0
  136. package/src/types/index.ts +1 -1
  137. package/src/types/message.ts +0 -1
  138. package/src/types/misc.ts +0 -2
  139. package/src/types/protocol.ts +0 -2
  140. package/src/types/run.ts +0 -3
  141. package/src/types/session.ts +1 -51
  142. package/src/types/swarmdock.ts +29 -0
  143. package/src/types/task.ts +7 -3
  144. package/src/types/working-state.ts +2 -9
  145. package/src/views/settings/section-runtime-loop.tsx +0 -14
  146. package/src/app/api/canvas/[sessionId]/route.ts +0 -35
  147. package/src/app/api/missions/[id]/actions/route.ts +0 -31
  148. package/src/app/api/missions/[id]/events/route.ts +0 -14
  149. package/src/app/api/missions/[id]/route.ts +0 -10
  150. package/src/app/api/missions/route.test.ts +0 -244
  151. package/src/app/api/missions/route.ts +0 -57
  152. package/src/app/api/wallets/[id]/approve/route.ts +0 -79
  153. package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
  154. package/src/app/api/wallets/[id]/send/route.ts +0 -113
  155. package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
  156. package/src/app/missions/[id]/page.tsx +0 -3
  157. package/src/app/missions/page.tsx +0 -685
  158. package/src/components/canvas/canvas-panel.tsx +0 -267
  159. package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
  160. package/src/components/wallets/wallet-panel.tsx +0 -1010
  161. package/src/components/wallets/wallet-section.tsx +0 -260
  162. package/src/features/missions/queries.ts +0 -23
  163. package/src/lib/canvas-content.test.ts +0 -360
  164. package/src/lib/canvas-content.ts +0 -198
  165. package/src/lib/server/canvas-content.test.ts +0 -32
  166. package/src/lib/server/canvas-content.ts +0 -6
  167. package/src/lib/server/ethereum.ts +0 -591
  168. package/src/lib/server/evm-swap.ts +0 -476
  169. package/src/lib/server/missions/mission-intent.test.ts +0 -63
  170. package/src/lib/server/missions/mission-intent.ts +0 -569
  171. package/src/lib/server/missions/mission-repository.ts +0 -74
  172. package/src/lib/server/missions/mission-service/actions.ts +0 -6
  173. package/src/lib/server/missions/mission-service/bindings.ts +0 -9
  174. package/src/lib/server/missions/mission-service/context.ts +0 -4
  175. package/src/lib/server/missions/mission-service/core.ts +0 -2271
  176. package/src/lib/server/missions/mission-service/queries.ts +0 -12
  177. package/src/lib/server/missions/mission-service/recovery.ts +0 -5
  178. package/src/lib/server/missions/mission-service/ticks.ts +0 -9
  179. package/src/lib/server/missions/mission-service.test.ts +0 -888
  180. package/src/lib/server/missions/mission-service.ts +0 -6
  181. package/src/lib/server/session-tools/canvas.ts +0 -105
  182. package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
  183. package/src/lib/server/session-tools/wallet.ts +0 -1287
  184. package/src/lib/server/solana.ts +0 -327
  185. package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
  186. package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
  187. package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
  188. package/src/lib/server/wallet/wallet-service.test.ts +0 -81
  189. package/src/lib/server/wallet/wallet-service.ts +0 -225
  190. package/src/lib/wallet/wallet-transactions.test.ts +0 -75
  191. package/src/lib/wallet/wallet-transactions.ts +0 -43
  192. package/src/lib/wallet/wallet.test.ts +0 -333
  193. package/src/lib/wallet/wallet.ts +0 -183
  194. package/src/types/mission.ts +0 -185
  195. package/src/views/settings/section-wallets.tsx +0 -35
@@ -2,7 +2,7 @@ import assert from 'node:assert/strict'
2
2
  import { test } from 'node:test'
3
3
 
4
4
  import { buildExecutionBrief, buildExecutionBriefContextBlock, serializeExecutionBriefForDelegation } from './execution-brief'
5
- import type { Mission, Session, SessionWorkingState } from '@/types'
5
+ import type { Session, SessionWorkingState } from '@/types'
6
6
 
7
7
  test('buildExecutionBrief prefers working state and folds in mission and run-context fallback data', () => {
8
8
  const session = {
@@ -31,25 +31,8 @@ test('buildExecutionBrief prefers working state and folds in mission and run-con
31
31
  },
32
32
  } satisfies Partial<Session> as Session
33
33
 
34
- const mission = {
35
- id: 'm1',
36
- source: 'chat',
37
- objective: 'Ship the release fix',
38
- status: 'active',
39
- phase: 'executing',
40
- currentStep: 'Verify staging auth',
41
- successCriteria: ['Restore staging deploys'],
42
- waitState: {
43
- kind: 'approval',
44
- reason: 'Waiting for deploy approval.',
45
- },
46
- createdAt: 1,
47
- updatedAt: 1,
48
- } satisfies Partial<Mission> as Mission
49
-
50
34
  const workingState = {
51
35
  sessionId: 's1',
52
- missionId: 'm1',
53
36
  objective: 'Ship the release fix safely',
54
37
  summary: 'Auth mismatch isolated to staging.',
55
38
  constraints: ['Do not change the API'],
@@ -79,7 +62,7 @@ test('buildExecutionBrief prefers working state and folds in mission and run-con
79
62
  updatedAt: 1,
80
63
  } satisfies SessionWorkingState
81
64
 
82
- const brief = buildExecutionBrief({ session, mission, workingState })
65
+ const brief = buildExecutionBrief({ session, workingState })
83
66
 
84
67
  assert.equal(brief.objective, 'Ship the release fix safely')
85
68
  assert.equal(brief.summary, 'Auth mismatch isolated to staging.')
@@ -87,11 +70,9 @@ test('buildExecutionBrief prefers working state and folds in mission and run-con
87
70
  assert.equal(brief.nextAction, 'Request deploy approval')
88
71
  assert.equal(brief.plan[0]?.text, 'Request deploy approval')
89
72
  assert.equal(brief.blockers[0], 'Deploy approval is pending. | next: Request deploy approval')
90
- assert.ok(brief.blockers.some((entry) => /waiting for deploy approval/i.test(entry)))
91
73
  assert.ok(brief.facts.some((entry) => /auth mismatch isolated to staging/i.test(entry)))
92
74
  assert.ok(brief.artifacts.some((entry) => /deploy\.log/i.test(entry)))
93
75
  assert.equal(brief.parentContext, 'Parent asked for a contained fix.')
94
- assert.equal(brief.missionPhase, 'executing')
95
76
  })
96
77
 
97
78
  test('buildExecutionBriefContextBlock renders a single canonical state block', () => {
@@ -139,7 +120,6 @@ test('buildExecutionBriefContextBlock renders a single canonical state block', (
139
120
  test('serializeExecutionBriefForDelegation creates a bounded handoff summary', () => {
140
121
  const text = serializeExecutionBriefForDelegation({
141
122
  sessionId: 's3',
142
- missionId: 'm3',
143
123
  objective: 'Repair the deployment pipeline',
144
124
  summary: 'The regression is isolated to the release job.',
145
125
  status: 'blocked',
@@ -153,9 +133,6 @@ test('serializeExecutionBriefForDelegation creates a bounded handoff summary', (
153
133
  artifacts: ['/tmp/project/release.log'],
154
134
  constraints: ['Keep the current release shape.'],
155
135
  successCriteria: ['Production deploy completes'],
156
- missionStatus: 'active',
157
- missionPhase: 'executing',
158
- waitState: null,
159
136
  evidenceRefs: [],
160
137
  parentContext: 'Parent is waiting on a concise status update.',
161
138
  })
@@ -2,7 +2,6 @@ import type {
2
2
  EvidenceRef,
3
3
  ExecutionBrief,
4
4
  ExecutionBriefPlanStep,
5
- Mission,
6
5
  Session,
7
6
  SessionWorkingState,
8
7
  WorkingPlanStep,
@@ -75,14 +74,8 @@ function dedupePlan(steps: ExecutionBriefPlanStep[]): ExecutionBriefPlanStep[] {
75
74
  return out
76
75
  }
77
76
 
78
- function inferStatus(mission: Mission | null | undefined, workingState: SessionWorkingState | null): WorkingStateStatus {
77
+ function inferStatus(workingState: SessionWorkingState | null): WorkingStateStatus {
79
78
  if (workingState?.status) return workingState.status
80
- if (!mission) return 'idle'
81
- if (mission.status === 'completed') return 'completed'
82
- if (mission.status === 'waiting') return 'waiting'
83
- if (mission.status === 'failed' || mission.phase === 'failed') return 'blocked'
84
- if (mission.waitState) return 'waiting'
85
- if (mission.phase === 'executing' || mission.phase === 'dispatching' || mission.phase === 'verifying') return 'progress'
86
79
  return 'idle'
87
80
  }
88
81
 
@@ -121,15 +114,14 @@ function buildFacts(workingState: SessionWorkingState | null, session: Session |
121
114
  return uniqueStrings([...activeFacts, ...runContextFacts], MAX_FACTS, 240)
122
115
  }
123
116
 
124
- function buildBlockers(workingState: SessionWorkingState | null, mission: Mission | null | undefined, session: Session | null): string[] {
117
+ function buildBlockers(workingState: SessionWorkingState | null, session: Session | null): string[] {
125
118
  const activeBlockers = workingState
126
119
  ? workingState.blockers
127
120
  .filter((blocker) => blocker.status === 'active')
128
121
  .map((blocker) => blocker.nextAction ? `${blocker.summary} | next: ${blocker.nextAction}` : blocker.summary)
129
122
  : []
130
- const missionBlockers = mission?.waitState?.reason ? [cleanText(mission.waitState.reason, 280)] : []
131
123
  const runContextBlockers = session?.runContext ? ensureRunContext(session.runContext).blockers : []
132
- return uniqueStrings([...activeBlockers, ...missionBlockers, ...runContextBlockers], MAX_BLOCKERS, 280)
124
+ return uniqueStrings([...activeBlockers, ...runContextBlockers], MAX_BLOCKERS, 280)
133
125
  }
134
126
 
135
127
  function buildArtifacts(workingState: SessionWorkingState | null): string[] {
@@ -147,8 +139,8 @@ function buildConstraints(workingState: SessionWorkingState | null, session: Ses
147
139
  return uniqueStrings([...(workingConstraints || []), ...(runContext?.constraints || [])], 10, 220)
148
140
  }
149
141
 
150
- function buildSuccessCriteria(workingState: SessionWorkingState | null, mission: Mission | null | undefined): string[] {
151
- return uniqueStrings([...(workingState?.successCriteria || []), ...(mission?.successCriteria || [])], 10, 220)
142
+ function buildSuccessCriteria(workingState: SessionWorkingState | null): string[] {
143
+ return uniqueStrings([...(workingState?.successCriteria || [])], 10, 220)
152
144
  }
153
145
 
154
146
  function buildEvidenceRefs(workingState: SessionWorkingState | null): EvidenceRef[] {
@@ -161,49 +153,40 @@ function buildEvidenceRefs(workingState: SessionWorkingState | null): EvidenceRe
161
153
  export function buildExecutionBrief(params: {
162
154
  sessionId?: string | null
163
155
  session?: Session | null
164
- mission?: Mission | null
156
+ mission?: null
165
157
  workingState?: SessionWorkingState | null
166
158
  }): ExecutionBrief {
167
159
  const session = params.session
168
160
  || (params.sessionId ? getSession(params.sessionId) || null : null)
169
- const mission = params.mission || null
170
161
  const workingState = params.workingState
171
- || (session?.id ? loadSessionWorkingState(session.id, { mission }) : null)
162
+ || (session?.id ? loadSessionWorkingState(session.id) : null)
172
163
  const runContext = session?.runContext ? ensureRunContext(session.runContext) : null
173
164
  const plan = buildPlan(workingState, session)
174
165
  const nextAction = cleanText(
175
166
  workingState?.nextAction
176
- || mission?.currentStep
177
167
  || plan.find((step) => step.status === 'active')?.text,
178
168
  240,
179
169
  ) || null
180
170
 
181
171
  return {
182
172
  sessionId: session?.id || params.sessionId || null,
183
- missionId: mission?.id || workingState?.missionId || null,
184
173
  objective: cleanMultiline(
185
174
  workingState?.objective
186
- || mission?.objective
187
175
  || runContext?.objective,
188
176
  900,
189
177
  ) || null,
190
178
  summary: cleanMultiline(
191
- workingState?.summary
192
- || mission?.verifierSummary
193
- || mission?.plannerSummary,
179
+ workingState?.summary,
194
180
  700,
195
181
  ) || null,
196
- status: inferStatus(mission, workingState),
182
+ status: inferStatus(workingState),
197
183
  nextAction,
198
184
  plan,
199
- blockers: buildBlockers(workingState, mission, session),
185
+ blockers: buildBlockers(workingState, session),
200
186
  facts: buildFacts(workingState, session),
201
187
  artifacts: buildArtifacts(workingState),
202
188
  constraints: buildConstraints(workingState, session),
203
- successCriteria: buildSuccessCriteria(workingState, mission),
204
- missionStatus: mission?.status || null,
205
- missionPhase: mission?.phase || null,
206
- waitState: mission?.waitState || null,
189
+ successCriteria: buildSuccessCriteria(workingState),
207
190
  evidenceRefs: buildEvidenceRefs(workingState),
208
191
  parentContext: cleanMultiline(runContext?.parentContext, 900) || null,
209
192
  }
@@ -238,10 +221,7 @@ export function buildExecutionBriefContextBlock(
238
221
  || brief.artifacts.length > 0
239
222
  || brief.constraints.length > 0
240
223
  || brief.successCriteria.length > 0
241
- || brief.evidenceRefs.length > 0
242
- || brief.missionStatus
243
- || brief.missionPhase
244
- || brief.waitState?.reason,
224
+ || brief.evidenceRefs.length > 0,
245
225
  )
246
226
  if (!hasContent && brief.status === 'idle') return ''
247
227
  const sections = [
@@ -250,9 +230,6 @@ export function buildExecutionBriefContextBlock(
250
230
  brief.objective ? `Objective: ${brief.objective}` : '',
251
231
  brief.summary ? `Summary: ${brief.summary}` : '',
252
232
  `Status: ${brief.status}`,
253
- brief.missionStatus ? `Mission status: ${brief.missionStatus}` : '',
254
- brief.missionPhase ? `Mission phase: ${brief.missionPhase}` : '',
255
- brief.waitState?.reason ? `Waiting reason: ${cleanText(brief.waitState.reason, 280)}` : '',
256
233
  brief.nextAction ? `Next action: ${brief.nextAction}` : '',
257
234
  brief.successCriteria.length > 0 ? `Success criteria: ${brief.successCriteria.join(' | ')}` : '',
258
235
  brief.constraints.length > 0 ? `Constraints: ${brief.constraints.join(' | ')}` : '',
@@ -238,7 +238,6 @@ export function enqueueTaskAttemptExecution(
238
238
  const run: SessionRunRecord = {
239
239
  id: executionId,
240
240
  sessionId: input.sessionId,
241
- missionId: input.task.missionId || null,
242
241
  kind: 'task_attempt',
243
242
  ownerType: 'task',
244
243
  ownerId: input.task.id,
@@ -5,7 +5,6 @@ import { approvalRepository } from '@/lib/server/approvals/approval-repository'
5
5
  import { chatroomRepository } from '@/lib/server/chatrooms/chatroom-repository'
6
6
  import { connectorRepository } from '@/lib/server/connectors/connector-repository'
7
7
  import * as messageRepository from '@/lib/server/messages/message-repository'
8
- import { missionEventRepository, missionRepository } from '@/lib/server/missions/mission-repository'
9
8
  import { projectRepository } from '@/lib/server/projects/project-repository'
10
9
  import { scheduleRepository } from '@/lib/server/schedules/schedule-repository'
11
10
  import { sessionRepository } from '@/lib/server/sessions/session-repository'
@@ -19,8 +18,6 @@ export interface StorageTxContext {
19
18
  chatrooms: typeof chatroomRepository
20
19
  connectors: typeof connectorRepository
21
20
  messages: typeof messageRepository
22
- missions: typeof missionRepository
23
- missionEvents: typeof missionEventRepository
24
21
  projects: typeof projectRepository
25
22
  runs: typeof runRepository
26
23
  runEvents: typeof runEventRepository
@@ -37,8 +34,6 @@ export function createStorageTxContext(): StorageTxContext {
37
34
  chatrooms: chatroomRepository,
38
35
  connectors: connectorRepository,
39
36
  messages: messageRepository,
40
- missions: missionRepository,
41
- missionEvents: missionEventRepository,
42
37
  projects: projectRepository,
43
38
  runs: runRepository,
44
39
  runEvents: runEventRepository,
@@ -0,0 +1,109 @@
1
+ import { loadAgents } from '@/lib/server/agents/agent-repository'
2
+ import { loadSkills } from '@/lib/server/skills/skill-repository'
3
+ import { loadSchedules } from '@/lib/server/schedules/schedule-repository'
4
+ import type { Agent } from '@/types/agent'
5
+ import type { Skill } from '@/types/skill'
6
+ import type { Schedule } from '@/types/schedule'
7
+
8
+ export const PORTABILITY_FORMAT_VERSION = 1
9
+
10
+ export interface PortableManifest {
11
+ formatVersion: number
12
+ exportedAt: string
13
+ agents: PortableAgent[]
14
+ skills: PortableSkill[]
15
+ schedules: PortableSchedule[]
16
+ }
17
+
18
+ export type PortableAgent = Omit<Agent,
19
+ // Strip runtime/sensitive fields
20
+ | 'id' | 'credentialId' | 'fallbackCredentialIds' | 'apiEndpoint'
21
+ | 'threadSessionId' | 'lastUsedAt' | 'totalCost' | 'trashedAt'
22
+ | 'openclawAgentId' | 'gatewayProfileId' | 'avatarUrl'
23
+ > & {
24
+ /** Original ID — used for matching during import */
25
+ originalId: string
26
+ }
27
+
28
+ export type PortableSkill = Pick<Skill,
29
+ | 'name' | 'content' | 'description' | 'tags' | 'scope'
30
+ | 'author' | 'version' | 'primaryEnv' | 'capabilities'
31
+ | 'toolNames' | 'frontmatter'
32
+ > & {
33
+ originalId: string
34
+ }
35
+
36
+ export type PortableSchedule = Pick<Schedule,
37
+ | 'name' | 'taskPrompt' | 'taskMode' | 'message' | 'description'
38
+ | 'scheduleType' | 'frequency' | 'cron' | 'atTime' | 'intervalMs'
39
+ | 'timezone' | 'action' | 'path' | 'command'
40
+ > & {
41
+ originalId: string
42
+ /** Original agent ID — resolved to new ID during import */
43
+ originalAgentId: string
44
+ }
45
+
46
+ /** Sensitive fields stripped from exported agents */
47
+ const AGENT_STRIP_KEYS: (keyof Agent)[] = [
48
+ 'id', 'credentialId', 'fallbackCredentialIds', 'apiEndpoint',
49
+ 'threadSessionId', 'lastUsedAt', 'totalCost', 'trashedAt',
50
+ 'openclawAgentId', 'gatewayProfileId', 'avatarUrl',
51
+ ]
52
+
53
+ export function exportConfig(): PortableManifest {
54
+ const agents = loadAgents()
55
+ const skills = loadSkills()
56
+ const schedules = loadSchedules()
57
+
58
+ const portableAgents: PortableAgent[] = Object.values(agents)
59
+ .filter((a) => !a.trashedAt && !a.disabled)
60
+ .map((agent) => {
61
+ const portable = { ...agent, originalId: agent.id } as Record<string, unknown>
62
+ for (const key of AGENT_STRIP_KEYS) delete portable[key]
63
+ return portable as PortableAgent
64
+ })
65
+
66
+ const portableSkills: PortableSkill[] = Object.values(skills).map((skill) => ({
67
+ originalId: skill.id,
68
+ name: skill.name,
69
+ content: skill.content,
70
+ description: skill.description,
71
+ tags: skill.tags,
72
+ scope: skill.scope,
73
+ author: skill.author,
74
+ version: skill.version,
75
+ primaryEnv: skill.primaryEnv,
76
+ capabilities: skill.capabilities,
77
+ toolNames: skill.toolNames,
78
+ frontmatter: skill.frontmatter,
79
+ }))
80
+
81
+ const portableSchedules: PortableSchedule[] = Object.values(schedules)
82
+ .filter((s) => s.status !== 'archived')
83
+ .map((schedule) => ({
84
+ originalId: schedule.id,
85
+ originalAgentId: schedule.agentId,
86
+ name: schedule.name,
87
+ taskPrompt: schedule.taskPrompt,
88
+ taskMode: schedule.taskMode,
89
+ message: schedule.message,
90
+ description: schedule.description,
91
+ scheduleType: schedule.scheduleType,
92
+ frequency: schedule.frequency,
93
+ cron: schedule.cron,
94
+ atTime: schedule.atTime,
95
+ intervalMs: schedule.intervalMs,
96
+ timezone: schedule.timezone,
97
+ action: schedule.action,
98
+ path: schedule.path,
99
+ command: schedule.command,
100
+ }))
101
+
102
+ return {
103
+ formatVersion: PORTABILITY_FORMAT_VERSION,
104
+ exportedAt: new Date().toISOString(),
105
+ agents: portableAgents,
106
+ skills: portableSkills,
107
+ schedules: portableSchedules,
108
+ }
109
+ }
@@ -0,0 +1,159 @@
1
+ import { genId } from '@/lib/id'
2
+ import { loadAgents, saveAgents } from '@/lib/server/agents/agent-repository'
3
+ import { loadSkills, saveSkill } from '@/lib/server/skills/skill-repository'
4
+ import { loadSchedules, upsertSchedule } from '@/lib/server/schedules/schedule-repository'
5
+ import { logActivity } from '@/lib/server/activity/activity-log'
6
+ import type { Agent } from '@/types/agent'
7
+ import type { Skill } from '@/types/skill'
8
+ import type { Schedule } from '@/types/schedule'
9
+ import type { PortableManifest, PortableAgent, PortableSkill, PortableSchedule } from './export'
10
+ import { PORTABILITY_FORMAT_VERSION } from './export'
11
+
12
+ export interface ImportResult {
13
+ agents: { created: number; skipped: number; names: string[] }
14
+ skills: { created: number; skipped: number; names: string[] }
15
+ schedules: { created: number; skipped: number; names: string[] }
16
+ /** Maps original IDs to new IDs for reference */
17
+ idMap: Record<string, string>
18
+ }
19
+
20
+ function deduplicateName(name: string, existingNames: Set<string>): string {
21
+ if (!existingNames.has(name)) return name
22
+ let suffix = 2
23
+ while (existingNames.has(`${name} (${suffix})`)) suffix++
24
+ return `${name} (${suffix})`
25
+ }
26
+
27
+ export function importConfig(manifest: PortableManifest): ImportResult {
28
+ if (manifest.formatVersion > PORTABILITY_FORMAT_VERSION) {
29
+ throw new Error(`Unsupported format version ${manifest.formatVersion} (max supported: ${PORTABILITY_FORMAT_VERSION})`)
30
+ }
31
+
32
+ const idMap: Record<string, string> = {}
33
+ const result: ImportResult = {
34
+ agents: { created: 0, skipped: 0, names: [] },
35
+ skills: { created: 0, skipped: 0, names: [] },
36
+ schedules: { created: 0, skipped: 0, names: [] },
37
+ idMap,
38
+ }
39
+
40
+ // --- Import skills first (agents may reference them) ---
41
+ const existingSkills = loadSkills()
42
+ const existingSkillNames = new Set(Object.values(existingSkills).map((s) => s.name))
43
+
44
+ for (const portable of manifest.skills) {
45
+ const name = deduplicateName(portable.name, existingSkillNames)
46
+ const id = genId()
47
+ idMap[portable.originalId] = id
48
+ existingSkillNames.add(name)
49
+
50
+ const skill: Skill = {
51
+ id,
52
+ name,
53
+ filename: `${name.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.md`,
54
+ content: portable.content,
55
+ description: portable.description,
56
+ tags: portable.tags,
57
+ scope: portable.scope || 'global',
58
+ author: portable.author,
59
+ version: portable.version,
60
+ primaryEnv: portable.primaryEnv,
61
+ capabilities: portable.capabilities,
62
+ toolNames: portable.toolNames,
63
+ frontmatter: portable.frontmatter,
64
+ createdAt: Date.now(),
65
+ updatedAt: Date.now(),
66
+ }
67
+ saveSkill(id, skill)
68
+ result.skills.created++
69
+ result.skills.names.push(name)
70
+ }
71
+
72
+ // --- Import agents ---
73
+ const existingAgents = loadAgents()
74
+ const existingAgentNames = new Set(Object.values(existingAgents).map((a) => a.name))
75
+
76
+ for (const portable of manifest.agents) {
77
+ const name = deduplicateName(portable.name, existingAgentNames)
78
+ const id = genId()
79
+ const now = Date.now()
80
+ idMap[portable.originalId] = id
81
+ existingAgentNames.add(name)
82
+
83
+ // Remap skill IDs if they were imported
84
+ const remappedSkillIds = (portable.skillIds || []).map((sid) => idMap[sid] || sid)
85
+
86
+ const agent: Agent = {
87
+ ...(portable as Omit<PortableAgent, 'originalId'>),
88
+ id,
89
+ name,
90
+ skillIds: remappedSkillIds,
91
+ // Reset runtime fields
92
+ threadSessionId: null,
93
+ lastUsedAt: undefined,
94
+ totalCost: undefined,
95
+ trashedAt: undefined,
96
+ credentialId: null,
97
+ fallbackCredentialIds: [],
98
+ apiEndpoint: null,
99
+ createdAt: typeof portable.createdAt === 'number' ? portable.createdAt : now,
100
+ updatedAt: now,
101
+ }
102
+ existingAgents[id] = agent
103
+ result.agents.created++
104
+ result.agents.names.push(name)
105
+ }
106
+
107
+ saveAgents(existingAgents)
108
+
109
+ // --- Import schedules (need agent ID mapping) ---
110
+ const existingSchedules = loadSchedules()
111
+ const existingScheduleNames = new Set(Object.values(existingSchedules).map((s) => s.name))
112
+
113
+ for (const portable of manifest.schedules) {
114
+ const newAgentId = idMap[portable.originalAgentId]
115
+ if (!newAgentId) {
116
+ result.schedules.skipped++
117
+ continue
118
+ }
119
+
120
+ const name = deduplicateName(portable.name, existingScheduleNames)
121
+ const id = genId()
122
+ idMap[portable.originalId] = id
123
+ existingScheduleNames.add(name)
124
+
125
+ const schedule: Schedule = {
126
+ id,
127
+ name,
128
+ agentId: newAgentId,
129
+ taskPrompt: portable.taskPrompt,
130
+ taskMode: portable.taskMode,
131
+ message: portable.message,
132
+ description: portable.description,
133
+ scheduleType: portable.scheduleType,
134
+ frequency: portable.frequency,
135
+ cron: portable.cron,
136
+ atTime: portable.atTime,
137
+ intervalMs: portable.intervalMs,
138
+ timezone: portable.timezone,
139
+ action: portable.action,
140
+ path: portable.path,
141
+ command: portable.command,
142
+ status: 'paused',
143
+ createdAt: Date.now(),
144
+ }
145
+ upsertSchedule(id, schedule)
146
+ result.schedules.created++
147
+ result.schedules.names.push(name)
148
+ }
149
+
150
+ logActivity({
151
+ entityType: 'system',
152
+ entityId: 'portability',
153
+ action: 'imported',
154
+ actor: 'user',
155
+ summary: `Imported ${result.agents.created} agents, ${result.skills.created} skills, ${result.schedules.created} schedules`,
156
+ })
157
+
158
+ return result
159
+ }
@@ -446,9 +446,6 @@ export function normalizeProtocolSourceRef(run: Partial<ProtocolRun>): ProtocolS
446
446
  if (typeof run.parentChatroomId === 'string' && run.parentChatroomId.trim()) {
447
447
  return { kind: 'chatroom', chatroomId: run.parentChatroomId.trim() }
448
448
  }
449
- if (typeof run.missionId === 'string' && run.missionId.trim()) {
450
- return { kind: 'mission', missionId: run.missionId.trim() }
451
- }
452
449
  if (typeof run.taskId === 'string' && run.taskId.trim()) {
453
450
  return { kind: 'task', taskId: run.taskId.trim() }
454
451
  }
@@ -484,7 +481,6 @@ export function normalizeProtocolRun(run: ProtocolRun): ProtocolRun {
484
481
  participantAgentIds: uniqueIds(run.participantAgentIds, 64),
485
482
  observerAgentIds: uniqueIds(run.observerAgentIds, 64),
486
483
  facilitatorAgentId: typeof run.facilitatorAgentId === 'string' ? run.facilitatorAgentId : null,
487
- missionId: typeof run.missionId === 'string' ? run.missionId : null,
488
484
  taskId: typeof run.taskId === 'string' ? run.taskId : null,
489
485
  sessionId: typeof run.sessionId === 'string' ? run.sessionId : null,
490
486
  parentRunId: typeof run.parentRunId === 'string' ? run.parentRunId : null,
@@ -13,9 +13,6 @@ import {
13
13
  loadChatroom,
14
14
  loadChatroomMany,
15
15
  } from '@/lib/server/chatrooms/chatroom-repository'
16
- import {
17
- loadMission,
18
- } from '@/lib/server/missions/mission-repository'
19
16
  import {
20
17
  loadProtocolRun,
21
18
  loadProtocolRuns,
@@ -37,7 +34,6 @@ export function listProtocolTemplates(): ProtocolTemplate[] {
37
34
 
38
35
  export function listProtocolRuns(options?: {
39
36
  status?: ProtocolRunStatus | null
40
- missionId?: string | null
41
37
  taskId?: string | null
42
38
  sessionId?: string | null
43
39
  parentChatroomId?: string | null
@@ -51,7 +47,6 @@ export function listProtocolRuns(options?: {
51
47
  return Object.values(loadProtocolRuns())
52
48
  .map((run) => normalizeProtocolRun(run))
53
49
  .filter((run) => !options?.status || run.status === options.status)
54
- .filter((run) => !options?.missionId || run.missionId === options.missionId)
55
50
  .filter((run) => !options?.taskId || run.taskId === options.taskId)
56
51
  .filter((run) => !options?.sessionId || run.sessionId === options.sessionId)
57
52
  .filter((run) => !options?.parentChatroomId || run.parentChatroomId === options.parentChatroomId)
@@ -109,7 +104,6 @@ export function getProtocolRunDetail(runId: string): ProtocolRunDetail | null {
109
104
  template: loadTemplate(run.templateId),
110
105
  transcript: run.transcriptChatroomId ? chatrooms[run.transcriptChatroomId] || null : null,
111
106
  parentChatroom: run.parentChatroomId ? chatrooms[run.parentChatroomId] || null : null,
112
- linkedMission: run.missionId ? loadMission(run.missionId) : null,
113
107
  linkedTask: run.taskId ? loadTask(run.taskId) : null,
114
108
  events: listEvents(run.id),
115
109
  }
@@ -19,7 +19,6 @@ import { patchChatroom, upsertChatroom } from '@/lib/server/chatrooms/chatroom-r
19
19
  import { loadProtocolRuns } from '@/lib/server/protocols/protocol-run-repository'
20
20
  import { loadTask } from '@/lib/server/tasks/task-repository'
21
21
  import { errorMessage, hmrSingleton } from '@/lib/shared-utils'
22
- import { requestMissionTick } from '@/lib/server/missions/mission-service'
23
22
  import { cleanText, isDiscussionStepKind, now, uniqueIds } from '@/lib/server/protocols/protocol-types'
24
23
  import type { CreateProtocolRunInput, ProtocolRunActionInput, ProtocolRunDeps } from '@/lib/server/protocols/protocol-types'
25
24
  import { deriveDisplayPhasesFromSteps, loadProtocolRunById, normalizeProtocolRun, resolveRunSteps } from '@/lib/server/protocols/protocol-normalization'
@@ -224,11 +223,10 @@ export function createProtocolRun(input: CreateProtocolRunInput, deps?: Protocol
224
223
  : null
225
224
  const sourceRef = input.sourceRef || (
226
225
  input.parentChatroomId ? { kind: 'chatroom', chatroomId: input.parentChatroomId } as ProtocolSourceRef
227
- : input.missionId ? { kind: 'mission', missionId: input.missionId } as ProtocolSourceRef
228
- : input.taskId ? { kind: 'task', taskId: input.taskId } as ProtocolSourceRef
229
- : input.scheduleId ? { kind: 'schedule', scheduleId: input.scheduleId } as ProtocolSourceRef
230
- : input.sessionId ? { kind: 'session', sessionId: input.sessionId } as ProtocolSourceRef
231
- : { kind: 'manual' } as ProtocolSourceRef
226
+ : input.taskId ? { kind: 'task', taskId: input.taskId } as ProtocolSourceRef
227
+ : input.scheduleId ? { kind: 'schedule', scheduleId: input.scheduleId } as ProtocolSourceRef
228
+ : input.sessionId ? { kind: 'session', sessionId: input.sessionId } as ProtocolSourceRef
229
+ : { kind: 'manual' } as ProtocolSourceRef
232
230
  )
233
231
  const runId = genId()
234
232
  if (transcript) {
@@ -246,7 +244,6 @@ export function createProtocolRun(input: CreateProtocolRunInput, deps?: Protocol
246
244
  participantAgentIds,
247
245
  facilitatorAgentId: cleanText(input.facilitatorAgentId, 64) || participantAgentIds[0] || null,
248
246
  observerAgentIds: uniqueIds(input.observerAgentIds, 32),
249
- missionId: cleanText(input.missionId, 64) || null,
250
247
  taskId: cleanText(input.taskId, 64) || null,
251
248
  sessionId: cleanText(input.sessionId, 64) || null,
252
249
  parentRunId: cleanText(input.parentRunId, 64) || null,
@@ -288,9 +285,6 @@ export function createProtocolRun(input: CreateProtocolRunInput, deps?: Protocol
288
285
  transcriptChatroomId: run.transcriptChatroomId,
289
286
  },
290
287
  }, deps)
291
- if (run.missionId) {
292
- requestMissionTick(run.missionId, 'protocol_run_created', { protocolRunId: run.id })
293
- }
294
288
  if (input.autoStart !== false) {
295
289
  requestProtocolRunExecution(run.id, deps)
296
290
  }
@@ -594,7 +588,6 @@ export function launchProtocolRunForSchedule(schedule: Schedule): ProtocolRun {
594
588
  observerAgentIds: uniqueIds(schedule.protocolObserverAgentIds, 32),
595
589
  scheduleId: schedule.id,
596
590
  sessionId: schedule.createdInSessionId || null,
597
- missionId: schedule.linkedMissionId || null,
598
591
  sourceRef: { kind: 'schedule', scheduleId: schedule.id },
599
592
  autoStart: true,
600
593
  parentChatroomId: null,
@@ -607,31 +600,11 @@ export function launchProtocolRunForSchedule(schedule: Schedule): ProtocolRun {
607
600
  })
608
601
  }
609
602
 
610
- export function launchProtocolRunForMission(input: {
611
- missionId: string
612
- title: string
613
- participantAgentIds: string[]
614
- facilitatorAgentId?: string | null
615
- config?: ProtocolRunConfig | null
616
- templateId?: string | null
617
- }): ProtocolRun {
618
- return createProtocolRun({
619
- title: input.title,
620
- templateId: input.templateId || 'facilitated_discussion',
621
- participantAgentIds: input.participantAgentIds,
622
- facilitatorAgentId: input.facilitatorAgentId || null,
623
- missionId: input.missionId,
624
- sourceRef: { kind: 'mission', missionId: input.missionId },
625
- config: input.config || null,
626
- })
627
- }
628
-
629
603
  export function launchProtocolRunForTask(input: {
630
604
  taskId: string
631
605
  title: string
632
606
  participantAgentIds: string[]
633
607
  facilitatorAgentId?: string | null
634
- missionId?: string | null
635
608
  config?: ProtocolRunConfig | null
636
609
  templateId?: string | null
637
610
  }): ProtocolRun {
@@ -640,7 +613,6 @@ export function launchProtocolRunForTask(input: {
640
613
  templateId: input.templateId || 'facilitated_discussion',
641
614
  participantAgentIds: input.participantAgentIds,
642
615
  facilitatorAgentId: input.facilitatorAgentId || null,
643
- missionId: input.missionId || null,
644
616
  taskId: input.taskId,
645
617
  sourceRef: { kind: 'task', taskId: input.taskId },
646
618
  config: input.config || null,
@@ -43,7 +43,6 @@ export {
43
43
  runProtocolRun,
44
44
  performProtocolRunAction,
45
45
  launchProtocolRunForSchedule,
46
- launchProtocolRunForMission,
47
46
  launchProtocolRunForTask,
48
47
  } from '@/lib/server/protocols/protocol-run-lifecycle'
49
48
 
@@ -36,7 +36,6 @@ import {
36
36
  updateRun,
37
37
  } from '@/lib/server/protocols/protocol-agent-turn'
38
38
  import { isTerminalProtocolRunStatus } from '@/lib/server/protocols/protocol-templates'
39
- import { requestMissionTick } from '@/lib/server/missions/mission-service'
40
39
 
41
40
  // ---- BranchDecisionSchema ----
42
41
 
@@ -329,9 +328,6 @@ export function completeProtocolRun(run: ProtocolRun, deps?: ProtocolRunDeps, su
329
328
  summary,
330
329
  }, deps)
331
330
  emitSummaryToParentChatroom(completed, deps)
332
- if (completed.missionId) {
333
- requestMissionTick(completed.missionId, 'protocol_run_completed', { protocolRunId: completed.id })
334
- }
335
331
  return completed
336
332
  }
337
333