@swarmclawai/swarmclaw 1.2.3 → 1.2.5

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 (273) hide show
  1. package/README.md +20 -0
  2. package/bin/daemon-cmd.js +169 -0
  3. package/bin/server-cmd.js +3 -0
  4. package/bin/swarmclaw.js +11 -0
  5. package/package.json +17 -16
  6. package/src/app/api/agents/[id]/clone/route.ts +3 -32
  7. package/src/app/api/agents/[id]/route.ts +6 -158
  8. package/src/app/api/agents/[id]/status/route.ts +2 -3
  9. package/src/app/api/agents/[id]/thread/route.ts +4 -17
  10. package/src/app/api/agents/bulk/route.ts +5 -47
  11. package/src/app/api/agents/route.ts +5 -119
  12. package/src/app/api/agents/trash/route.ts +13 -24
  13. package/src/app/api/auth/route.ts +3 -9
  14. package/src/app/api/autonomy/estop/route.ts +5 -5
  15. package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
  16. package/src/app/api/chatrooms/[id]/route.ts +23 -2
  17. package/src/app/api/chatrooms/route.ts +13 -2
  18. package/src/app/api/chats/[id]/clear/route.ts +2 -13
  19. package/src/app/api/chats/[id]/deploy/route.ts +2 -3
  20. package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
  21. package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
  22. package/src/app/api/chats/[id]/queue/route.ts +17 -64
  23. package/src/app/api/chats/[id]/retry/route.ts +4 -22
  24. package/src/app/api/chats/[id]/route.ts +10 -138
  25. package/src/app/api/chats/heartbeat/route.ts +2 -1
  26. package/src/app/api/chats/migrate-messages/route.ts +7 -0
  27. package/src/app/api/chats/route.ts +13 -134
  28. package/src/app/api/connectors/[id]/access/route.ts +12 -229
  29. package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
  30. package/src/app/api/connectors/[id]/health/route.ts +12 -39
  31. package/src/app/api/connectors/[id]/route.ts +14 -122
  32. package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
  33. package/src/app/api/connectors/doctor/route.ts +1 -1
  34. package/src/app/api/connectors/route.ts +12 -70
  35. package/src/app/api/credentials/[id]/route.ts +2 -4
  36. package/src/app/api/credentials/route.ts +10 -19
  37. package/src/app/api/daemon/health-check/route.ts +3 -4
  38. package/src/app/api/daemon/route.ts +10 -8
  39. package/src/app/api/documents/route.ts +11 -10
  40. package/src/app/api/external-agents/route.ts +3 -3
  41. package/src/app/api/gateways/[id]/health/route.ts +2 -3
  42. package/src/app/api/gateways/[id]/route.ts +7 -122
  43. package/src/app/api/gateways/route.ts +3 -103
  44. package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
  45. package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
  46. package/src/app/api/openclaw/directory/route.ts +2 -2
  47. package/src/app/api/openclaw/history/route.ts +3 -5
  48. package/src/app/api/providers/[id]/models/route.test.ts +60 -0
  49. package/src/app/api/providers/[id]/models/route.ts +33 -1
  50. package/src/app/api/providers/[id]/route.test.ts +49 -0
  51. package/src/app/api/providers/[id]/route.ts +30 -1
  52. package/src/app/api/providers/ollama/route.ts +6 -5
  53. package/src/app/api/schedules/[id]/route.ts +14 -108
  54. package/src/app/api/schedules/[id]/run/route.ts +6 -67
  55. package/src/app/api/schedules/route.ts +9 -51
  56. package/src/app/api/settings/route.ts +4 -3
  57. package/src/app/api/setup/check-provider/route.ts +15 -1
  58. package/src/app/api/setup/openclaw-device/route.ts +2 -2
  59. package/src/app/api/system/status/route.ts +2 -2
  60. package/src/app/api/tasks/[id]/route.ts +16 -202
  61. package/src/app/api/tasks/bulk/route.ts +5 -86
  62. package/src/app/api/tasks/metrics/route.ts +2 -1
  63. package/src/app/api/tasks/route.ts +11 -171
  64. package/src/app/api/upload/route.ts +1 -1
  65. package/src/app/api/uploads/[filename]/route.ts +1 -1
  66. package/src/app/api/uploads/route.ts +1 -1
  67. package/src/app/api/webhooks/[id]/history/route.ts +2 -2
  68. package/src/app/layout.tsx +9 -6
  69. package/src/app/protocols/page.tsx +71 -89
  70. package/src/app/tasks/page.tsx +32 -32
  71. package/src/cli/index.js +1 -0
  72. package/src/cli/spec.js +1 -0
  73. package/src/components/agents/agent-sheet.tsx +51 -25
  74. package/src/components/agents/inspector-panel.tsx +15 -4
  75. package/src/components/auth/setup-wizard/index.tsx +27 -18
  76. package/src/components/auth/setup-wizard/shared.tsx +2 -2
  77. package/src/components/auth/setup-wizard/step-agents.tsx +51 -38
  78. package/src/components/auth/setup-wizard/step-connect.tsx +48 -17
  79. package/src/components/auth/setup-wizard/types.ts +6 -4
  80. package/src/components/auth/setup-wizard/utils.test.ts +38 -8
  81. package/src/components/auth/setup-wizard/utils.ts +14 -8
  82. package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
  83. package/src/components/connectors/connector-list.tsx +26 -40
  84. package/src/components/connectors/connector-sheet.tsx +95 -149
  85. package/src/components/gateways/gateway-sheet.tsx +61 -110
  86. package/src/components/layout/live-query-sync.tsx +121 -0
  87. package/src/components/protocols/structured-session-launcher.tsx +24 -45
  88. package/src/components/providers/app-query-provider.tsx +17 -0
  89. package/src/components/providers/provider-list.tsx +150 -77
  90. package/src/components/providers/provider-sheet.tsx +102 -77
  91. package/src/components/shared/model-combobox.tsx +5 -4
  92. package/src/components/skills/skill-list.tsx +5 -18
  93. package/src/components/skills/skill-sheet.tsx +21 -20
  94. package/src/components/skills/skills-workspace.tsx +48 -87
  95. package/src/components/tasks/task-card.tsx +20 -13
  96. package/src/components/tasks/task-column.tsx +22 -7
  97. package/src/components/tasks/task-list.tsx +8 -11
  98. package/src/components/tasks/task-sheet.tsx +111 -103
  99. package/src/features/agents/queries.ts +20 -0
  100. package/src/features/chatrooms/queries.ts +20 -0
  101. package/src/features/chats/queries.ts +27 -0
  102. package/src/features/connectors/queries.ts +145 -0
  103. package/src/features/credentials/queries.ts +37 -0
  104. package/src/features/extensions/queries.ts +26 -0
  105. package/src/features/external-agents/queries.ts +36 -0
  106. package/src/features/gateways/queries.ts +274 -0
  107. package/src/features/missions/queries.ts +23 -0
  108. package/src/features/projects/queries.ts +20 -0
  109. package/src/features/protocols/queries.ts +149 -0
  110. package/src/features/providers/queries.ts +142 -0
  111. package/src/features/settings/queries.ts +20 -0
  112. package/src/features/skills/queries.ts +182 -0
  113. package/src/features/tasks/queries.ts +189 -0
  114. package/src/hooks/use-ws.ts +3 -2
  115. package/src/lib/agent-provider-options.test.ts +152 -0
  116. package/src/lib/agent-provider-options.ts +84 -0
  117. package/src/lib/app/api-client.ts +2 -2
  118. package/src/lib/providers/index.test.ts +78 -0
  119. package/src/lib/providers/index.ts +13 -10
  120. package/src/lib/query/client.ts +17 -0
  121. package/src/lib/server/agents/agent-runtime-config.ts +6 -6
  122. package/src/lib/server/agents/agent-service.ts +429 -0
  123. package/src/lib/server/agents/agent-thread-session.ts +6 -5
  124. package/src/lib/server/agents/autonomy-contract.ts +1 -4
  125. package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
  126. package/src/lib/server/agents/delegation-advisory.ts +251 -0
  127. package/src/lib/server/agents/main-agent-loop.ts +98 -40
  128. package/src/lib/server/agents/subagent-runtime.ts +12 -0
  129. package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
  130. package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
  131. package/src/lib/server/build-llm.ts +7 -15
  132. package/src/lib/server/capability-router.test.ts +70 -1
  133. package/src/lib/server/capability-router.ts +24 -99
  134. package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
  135. package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
  136. package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
  137. package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
  138. package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
  139. package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
  140. package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
  141. package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
  142. package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
  143. package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
  144. package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
  145. package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
  146. package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
  147. package/src/lib/server/chat-execution/message-classifier.ts +74 -32
  148. package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
  149. package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
  150. package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
  151. package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
  152. package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
  153. package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
  154. package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
  155. package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
  156. package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
  157. package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
  158. package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
  159. package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
  160. package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
  161. package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
  162. package/src/lib/server/chats/chat-session-service.ts +410 -0
  163. package/src/lib/server/connectors/access.ts +1 -1
  164. package/src/lib/server/connectors/commands.ts +7 -6
  165. package/src/lib/server/connectors/connector-inbound.ts +14 -7
  166. package/src/lib/server/connectors/connector-outbound.ts +16 -11
  167. package/src/lib/server/connectors/connector-service.ts +453 -0
  168. package/src/lib/server/connectors/delivery.ts +17 -12
  169. package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
  170. package/src/lib/server/connectors/media.ts +1 -1
  171. package/src/lib/server/connectors/response-media.ts +1 -1
  172. package/src/lib/server/connectors/session-consolidation.ts +11 -7
  173. package/src/lib/server/connectors/session.ts +9 -7
  174. package/src/lib/server/connectors/voice-note.ts +2 -1
  175. package/src/lib/server/context-manager.ts +20 -1
  176. package/src/lib/server/cost.ts +2 -3
  177. package/src/lib/server/credentials/credential-repository.ts +43 -4
  178. package/src/lib/server/credentials/credential-service.ts +112 -0
  179. package/src/lib/server/daemon/admin-metadata.ts +64 -0
  180. package/src/lib/server/daemon/controller.ts +577 -0
  181. package/src/lib/server/daemon/daemon-runtime.ts +352 -0
  182. package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
  183. package/src/lib/server/daemon/types.ts +101 -0
  184. package/src/lib/server/embeddings.ts +3 -9
  185. package/src/lib/server/eval/agent-regression.ts +3 -2
  186. package/src/lib/server/eval/runner.ts +2 -2
  187. package/src/lib/server/execution-brief.test.ts +167 -0
  188. package/src/lib/server/execution-brief.ts +295 -0
  189. package/src/lib/server/execution-engine/chat-turn.ts +9 -0
  190. package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
  191. package/src/lib/server/execution-engine/index.ts +35 -0
  192. package/src/lib/server/execution-engine/task-attempt.ts +303 -0
  193. package/src/lib/server/execution-engine/types.ts +33 -0
  194. package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
  195. package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
  196. package/src/lib/server/memory/session-archive-memory.ts +12 -10
  197. package/src/lib/server/messages/message-repository.ts +330 -0
  198. package/src/lib/server/missions/mission-service/core.ts +8 -6
  199. package/src/lib/server/openclaw/agent-resolver.ts +2 -3
  200. package/src/lib/server/openclaw/doctor.ts +1 -1
  201. package/src/lib/server/openclaw/gateway.test.ts +10 -1
  202. package/src/lib/server/openclaw/gateway.ts +5 -14
  203. package/src/lib/server/openclaw/health.ts +3 -11
  204. package/src/lib/server/openclaw/sync.ts +8 -6
  205. package/src/lib/server/persistence/storage-context.ts +3 -0
  206. package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
  207. package/src/lib/server/protocols/protocol-normalization.ts +1 -1
  208. package/src/lib/server/protocols/protocol-queries.ts +13 -7
  209. package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
  210. package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
  211. package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
  212. package/src/lib/server/protocols/protocol-swarm.ts +8 -8
  213. package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
  214. package/src/lib/server/protocols/protocol-templates.ts +4 -2
  215. package/src/lib/server/protocols/protocol-types.ts +10 -7
  216. package/src/lib/server/provider-endpoint.ts +7 -12
  217. package/src/lib/server/provider-model-discovery.ts +2 -11
  218. package/src/lib/server/query-expansion.ts +5 -6
  219. package/src/lib/server/run-context.test.ts +365 -0
  220. package/src/lib/server/run-context.ts +367 -0
  221. package/src/lib/server/runtime/heartbeat-service.ts +7 -5
  222. package/src/lib/server/runtime/queue/core.ts +61 -190
  223. package/src/lib/server/runtime/run-ledger.ts +8 -0
  224. package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
  225. package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
  226. package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
  227. package/src/lib/server/schedules/schedule-route-service.ts +230 -0
  228. package/src/lib/server/service-result.ts +16 -0
  229. package/src/lib/server/session-note.ts +2 -3
  230. package/src/lib/server/session-reset-policy.ts +4 -3
  231. package/src/lib/server/session-tools/connector.ts +9 -6
  232. package/src/lib/server/session-tools/context-mgmt.ts +58 -9
  233. package/src/lib/server/session-tools/crud.ts +162 -10
  234. package/src/lib/server/session-tools/delegate.ts +1 -1
  235. package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
  236. package/src/lib/server/session-tools/memory.ts +6 -4
  237. package/src/lib/server/session-tools/session-info.test.ts +56 -0
  238. package/src/lib/server/session-tools/session-info.ts +119 -12
  239. package/src/lib/server/session-tools/skill-runtime.ts +3 -1
  240. package/src/lib/server/session-tools/skills.ts +15 -15
  241. package/src/lib/server/session-tools/subagent.test.ts +115 -1
  242. package/src/lib/server/session-tools/subagent.ts +125 -7
  243. package/src/lib/server/session-tools/team-context.ts +4 -3
  244. package/src/lib/server/session-tools/wallet.ts +0 -58
  245. package/src/lib/server/sessions/session-lineage.ts +55 -0
  246. package/src/lib/server/sessions/session-repository.ts +2 -2
  247. package/src/lib/server/skills/learned-skills.ts +24 -23
  248. package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
  249. package/src/lib/server/skills/skill-repository.ts +136 -13
  250. package/src/lib/server/skills/skill-suggestions.ts +25 -28
  251. package/src/lib/server/storage-normalization.test.ts +42 -215
  252. package/src/lib/server/storage-normalization.ts +98 -0
  253. package/src/lib/server/storage.ts +19 -0
  254. package/src/lib/server/structured-extract.ts +3 -14
  255. package/src/lib/server/tasks/task-followups.ts +16 -11
  256. package/src/lib/server/tasks/task-result.test.ts +25 -29
  257. package/src/lib/server/tasks/task-result.ts +5 -9
  258. package/src/lib/server/tasks/task-route-service.ts +449 -0
  259. package/src/lib/server/text-normalization.ts +41 -0
  260. package/src/lib/server/tool-planning.ts +6 -42
  261. package/src/lib/server/upload-path.ts +5 -0
  262. package/src/lib/server/working-state/extraction.ts +614 -0
  263. package/src/lib/server/working-state/normalization.ts +866 -0
  264. package/src/lib/server/working-state/prompt.ts +60 -0
  265. package/src/lib/server/working-state/repository.ts +38 -0
  266. package/src/lib/server/working-state/service.test.ts +253 -0
  267. package/src/lib/server/working-state/service.ts +293 -0
  268. package/src/lib/validation/schemas.ts +1 -0
  269. package/src/lib/ws-client.ts +3 -3
  270. package/src/stores/slices/task-slice.ts +1 -4
  271. package/src/stores/use-chatroom-store.ts +2 -2
  272. package/src/types/index.ts +288 -22
  273. package/src/views/settings/section-providers.tsx +2 -2
@@ -3,7 +3,9 @@
3
3
  * Populates the field from existing senderId, senderIdAlt, channelId, channelIdAlt, peerKey.
4
4
  */
5
5
  import { log } from '@/lib/server/logger'
6
- import { loadSessions, loadSettings, saveSettings, upsertStoredItem } from '../storage'
6
+ import { saveSession, loadSessions } from '@/lib/server/sessions/session-repository'
7
+ import { getMessages, getMessageCount, replaceAllMessages } from '@/lib/server/messages/message-repository'
8
+ import { loadSettings, saveSettings } from '../settings/settings-repository'
7
9
  import type { Session } from '@/types'
8
10
  import { isDirectConnectorSession } from './session-kind'
9
11
 
@@ -38,7 +40,7 @@ export function backfillAllKnownPeerIds(): { migrated: number; skipped: boolean
38
40
  ...ctx,
39
41
  allKnownPeerIds: [...ids],
40
42
  }
41
- upsertStoredItem('sessions', session.id, session)
43
+ saveSession(session.id, session)
42
44
  migrated++
43
45
  }
44
46
 
@@ -63,19 +65,21 @@ export function pruneThreadConnectorMirrors(): { cleanedSessions: number; remove
63
65
 
64
66
  for (const session of Object.values(sessions)) {
65
67
  if (isDirectConnectorSession(session)) continue
66
- if (!Array.isArray(session.messages) || session.messages.length === 0) continue
68
+ const msgCount = getMessageCount(session.id)
69
+ if (msgCount === 0) continue
67
70
 
68
- const filteredMessages = session.messages.filter((message) => !(
71
+ const allMessages = getMessages(session.id)
72
+ const filteredMessages = allMessages.filter((message) => !(
69
73
  message?.historyExcluded === true
70
74
  && typeof message?.source?.connectorId === 'string'
71
75
  && message.source.connectorId.trim().length > 0
72
76
  ))
73
77
 
74
- const removed = session.messages.length - filteredMessages.length
78
+ const removed = allMessages.length - filteredMessages.length
75
79
  if (removed <= 0) continue
76
80
 
77
- session.messages = filteredMessages
78
- upsertStoredItem('sessions', session.id, session)
81
+ replaceAllMessages(session.id, filteredMessages)
82
+ saveSession(session.id, session)
79
83
  cleanedSessions += 1
80
84
  removedMessages += removed
81
85
  }
@@ -5,6 +5,10 @@ import { WORKSPACE_DIR } from '../data-dir'
5
5
  import { ensureAgentThreadSession } from '@/lib/server/agents/agent-thread-session'
6
6
  import { resolveEffectiveSessionMemoryScopeMode } from '@/lib/server/memory/session-memory-scope'
7
7
  import { syncSessionArchiveMemory } from '@/lib/server/memory/session-archive-memory'
8
+ import {
9
+ appendMessage,
10
+ getLastMessage,
11
+ } from '@/lib/server/messages/message-repository'
8
12
  import { loadAgents, loadSessions, loadStoredItem, upsertStoredItem } from '../storage'
9
13
  import { notify } from '../ws-hub'
10
14
  import {
@@ -416,7 +420,7 @@ function mirrorConnectorMessageToAgentThread(
416
420
  : ensureAgentThreadSession(session.agentId)
417
421
  if (!threadSession || threadSession.id === session.id) return
418
422
 
419
- const last = Array.isArray(threadSession.messages) ? threadSession.messages[threadSession.messages.length - 1] : null
423
+ const last = getLastMessage(threadSession.id)
420
424
  const source = message.source as MessageSource | undefined
421
425
  const lastSource = (last?.source || null) as MessageSource | null
422
426
  if (
@@ -431,17 +435,16 @@ function mirrorConnectorMessageToAgentThread(
431
435
  return
432
436
  }
433
437
 
434
- if (!Array.isArray(threadSession.messages)) threadSession.messages = []
435
- threadSession.messages.push({
438
+ const mirrorMsg = {
436
439
  ...message,
437
440
  time: typeof message.time === 'number' ? message.time : Date.now(),
438
441
  historyExcluded: true,
439
- } as Session['messages'][number])
442
+ } as Session['messages'][number]
443
+ appendMessage(threadSession.id, mirrorMsg)
440
444
  threadSession.lastActiveAt = Date.now()
441
445
 
442
446
  upsertStoredItem('sessions', threadSession.id, threadSession)
443
447
  notify('sessions')
444
- notify(`messages:${threadSession.id}`)
445
448
  }
446
449
 
447
450
  export function pushSessionMessage(
@@ -451,9 +454,8 @@ export function pushSessionMessage(
451
454
  extra: Record<string, unknown> = {},
452
455
  ): void {
453
456
  if (!text.trim()) return
454
- if (!Array.isArray(session.messages)) session.messages = []
455
457
  const message = { role, text: text.trim(), time: Date.now(), ...extra }
456
- session.messages.push(message)
458
+ appendMessage(session.id, message as Session['messages'][number])
457
459
  session.lastActiveAt = Date.now()
458
460
  mirrorConnectorMessageToAgentThread(session, message)
459
461
  }
@@ -1,8 +1,9 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
3
  import { genId } from '@/lib/id'
4
- import { loadAgent, UPLOAD_DIR } from '../storage'
4
+ import { loadAgent } from '@/lib/server/agents/agent-repository'
5
5
  import { synthesizeElevenLabsMp3 } from '../elevenlabs'
6
+ import { UPLOAD_DIR } from '../upload-path'
6
7
  import { isAudioMime, mimeFromPath } from './media'
7
8
 
8
9
  export function resolveConnectorVoiceId(params: {
@@ -1,5 +1,7 @@
1
- import type { Message } from '@/types'
1
+ import type { Message, Session } from '@/types'
2
2
  import { getMemoryDb } from '@/lib/server/memory/memory-db'
3
+ import { extractFactsFromMessages, ensureRunContext, pruneRunContext } from '@/lib/server/run-context'
4
+ import { getSession, saveSession } from '@/lib/server/sessions/session-repository'
3
5
 
4
6
  import { repairTranscriptConsistency } from './transcript-repair'
5
7
 
@@ -549,6 +551,23 @@ export async function llmCompact(opts: {
549
551
  const oldMessages = repaired.slice(0, -keepLastN)
550
552
  const recentMessages = repaired.slice(-keepLastN)
551
553
 
554
+ // 0. Extract facts from messages about to be dropped into RunContext (non-critical)
555
+ try {
556
+ const session = getSession(sessionId) as Session | undefined
557
+ if (session && oldMessages.length > 0) {
558
+ const extracted = extractFactsFromMessages(oldMessages)
559
+ if (extracted.keyFacts.length > 0 || extracted.failedApproaches.length > 0) {
560
+ const ctx = ensureRunContext(session.runContext)
561
+ ctx.keyFacts = [...ctx.keyFacts, ...extracted.keyFacts]
562
+ ctx.failedApproaches = [...ctx.failedApproaches, ...extracted.failedApproaches]
563
+ ctx.version++
564
+ ctx.updatedAt = Date.now()
565
+ session.runContext = pruneRunContext(ctx)
566
+ saveSession(sessionId, session)
567
+ }
568
+ }
569
+ } catch { /* non-critical — compaction continues even if extraction fails */ }
570
+
552
571
  // 1. Consolidate important info to memory
553
572
  const memoriesStored = consolidateToMemory(oldMessages, agentId, sessionId)
554
573
 
@@ -1,4 +1,4 @@
1
- import type { Agent, UsageRecord, ExtensionDefinitionCost } from '@/types'
1
+ import type { Agent, Session, UsageRecord, ExtensionDefinitionCost } from '@/types'
2
2
  import type { StructuredToolInterface } from '@langchain/core/tools'
3
3
  import { loadSessions, loadUsage } from './storage'
4
4
 
@@ -26,8 +26,7 @@ const MODEL_COSTS: Record<string, [number, number]> = {
26
26
  const ONE_HOUR_MS = 60 * 60 * 1000
27
27
  const WARNING_RATIO = 0.8
28
28
 
29
- type GenericRecord = Record<string, unknown>
30
- type SessionsMap = Record<string, GenericRecord>
29
+ type SessionsMap = Record<string, Session | Record<string, unknown>>
31
30
  type UsageMap = Record<string, unknown>
32
31
 
33
32
  function parsePositiveBudget(value: unknown): number | null {
@@ -1,7 +1,46 @@
1
- export {
1
+ import type { Credential } from '@/types'
2
+
3
+ import {
2
4
  decryptKey,
3
- deleteCredential,
5
+ deleteCredential as deleteStoredCredential,
4
6
  encryptKey,
5
- loadCredentials,
6
- saveCredentials,
7
+ loadCredentials as loadStoredCredentials,
8
+ saveCredentials as saveStoredCredentials,
9
+ upsertStoredItem,
7
10
  } from '@/lib/server/storage'
11
+ import { createRecordRepository } from '@/lib/server/persistence/repository-utils'
12
+
13
+ export type StoredCredential = Credential & {
14
+ encryptedKey?: string | null
15
+ updatedAt?: number
16
+ [key: string]: unknown
17
+ }
18
+
19
+ export const credentialRepository = createRecordRepository<StoredCredential>(
20
+ 'credentials',
21
+ {
22
+ get(id) {
23
+ return (loadStoredCredentials() as Record<string, StoredCredential>)[id] || null
24
+ },
25
+ list() {
26
+ return loadStoredCredentials() as Record<string, StoredCredential>
27
+ },
28
+ upsert(id, value) {
29
+ upsertStoredItem('credentials', id, value)
30
+ },
31
+ replace(data) {
32
+ saveStoredCredentials(data)
33
+ },
34
+ delete(id) {
35
+ deleteStoredCredential(id)
36
+ },
37
+ },
38
+ )
39
+
40
+ export const loadCredentials = () => credentialRepository.list()
41
+ export const loadCredential = (id: string) => credentialRepository.get(id)
42
+ export const saveCredentials = (items: Record<string, StoredCredential | Record<string, unknown>>) => credentialRepository.replace(items as Record<string, StoredCredential>)
43
+ export const saveCredential = (id: string, value: StoredCredential | Record<string, unknown>) => credentialRepository.upsert(id, value as StoredCredential)
44
+ export const deleteCredential = (id: string) => credentialRepository.delete(id)
45
+
46
+ export { decryptKey, encryptKey }
@@ -0,0 +1,112 @@
1
+ import type { Credential } from '@/types'
2
+
3
+ import { genId } from '@/lib/id'
4
+ import {
5
+ deleteCredential,
6
+ decryptKey,
7
+ encryptKey,
8
+ loadCredential,
9
+ loadCredentials,
10
+ saveCredential,
11
+ } from '@/lib/server/credentials/credential-repository'
12
+
13
+ export type CredentialSummary = Pick<Credential, 'id' | 'provider' | 'name' | 'createdAt'>
14
+
15
+ function clean(value: string | null | undefined): string {
16
+ return typeof value === 'string' ? value.trim() : ''
17
+ }
18
+
19
+ function toCredentialSummary(credential: Credential | null | undefined): CredentialSummary | null {
20
+ if (!credential) return null
21
+ return {
22
+ id: credential.id,
23
+ provider: credential.provider,
24
+ name: credential.name,
25
+ createdAt: credential.createdAt,
26
+ }
27
+ }
28
+
29
+ export function listCredentialSummaries(): Record<string, CredentialSummary> {
30
+ const credentials = loadCredentials()
31
+ const summaries: Record<string, CredentialSummary> = {}
32
+ for (const [id, credential] of Object.entries(credentials)) {
33
+ const summary = toCredentialSummary(credential)
34
+ if (summary) summaries[id] = summary
35
+ }
36
+ return summaries
37
+ }
38
+
39
+ export function getCredentialSummary(id: string): CredentialSummary | null {
40
+ return toCredentialSummary(loadCredential(id))
41
+ }
42
+
43
+ export function listCredentialIdsByProvider(provider: string): string[] {
44
+ const normalizedProvider = clean(provider)
45
+ if (!normalizedProvider) return []
46
+ return Object.entries(loadCredentials())
47
+ .filter(([, credential]) => credential?.provider === normalizedProvider)
48
+ .map(([id]) => id)
49
+ }
50
+
51
+ export function resolveCredentialSecret(credentialId: string | null | undefined): string | null {
52
+ const id = clean(credentialId)
53
+ if (!id) return null
54
+ const credential = loadCredential(id)
55
+ if (!credential?.encryptedKey) return null
56
+ try {
57
+ return decryptKey(credential.encryptedKey)
58
+ } catch {
59
+ return null
60
+ }
61
+ }
62
+
63
+ export function requireCredentialSecret(
64
+ credentialId: string | null | undefined,
65
+ missingMessage = 'Credential secret not found.',
66
+ ): string {
67
+ const id = clean(credentialId)
68
+ if (!id) throw new Error(missingMessage)
69
+ const credential = loadCredential(id)
70
+ if (!credential?.encryptedKey) throw new Error(missingMessage)
71
+ try {
72
+ return decryptKey(credential.encryptedKey)
73
+ } catch {
74
+ throw new Error(missingMessage)
75
+ }
76
+ }
77
+
78
+ export function createCredentialRecord(input: {
79
+ provider: string
80
+ name?: string | null
81
+ apiKey: string
82
+ }): CredentialSummary {
83
+ const provider = clean(input.provider)
84
+ const apiKey = clean(input.apiKey)
85
+ if (!provider || !apiKey) {
86
+ throw new Error('provider and apiKey are required')
87
+ }
88
+ const id = `cred_${genId(6)}`
89
+ const createdAt = Date.now()
90
+ const credentialName = clean(input.name) || `${provider} key`
91
+ saveCredential(id, {
92
+ id,
93
+ provider,
94
+ name: credentialName,
95
+ encryptedKey: encryptKey(apiKey),
96
+ createdAt,
97
+ })
98
+ return {
99
+ id,
100
+ provider,
101
+ name: credentialName,
102
+ createdAt,
103
+ }
104
+ }
105
+
106
+ export function deleteCredentialRecord(id: string): boolean {
107
+ const credentialId = clean(id)
108
+ if (!credentialId) return false
109
+ if (!loadCredential(credentialId)) return false
110
+ deleteCredential(credentialId)
111
+ return true
112
+ }
@@ -0,0 +1,64 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import { DATA_DIR } from '@/lib/server/data-dir'
5
+ import type { DaemonAdminMetadata } from '@/lib/server/daemon/types'
6
+
7
+ function resolveHomeDir(): string {
8
+ const configured = process.env.SWARMCLAW_HOME?.trim()
9
+ if (configured) return path.resolve(configured)
10
+ return path.dirname(DATA_DIR)
11
+ }
12
+
13
+ export const DAEMON_ADMIN_METADATA_PATH = path.join(resolveHomeDir(), 'daemon-admin.json')
14
+ export const DAEMON_LOG_PATH = path.join(resolveHomeDir(), 'daemon.log')
15
+
16
+ export function isProcessRunning(pid: number | null | undefined): boolean {
17
+ if (typeof pid !== 'number' || !Number.isFinite(pid) || pid <= 0) return false
18
+ try {
19
+ process.kill(pid, 0)
20
+ return true
21
+ } catch {
22
+ return false
23
+ }
24
+ }
25
+
26
+ function normalizeMetadata(value: unknown): DaemonAdminMetadata | null {
27
+ if (!value || typeof value !== 'object') return null
28
+ const candidate = value as Partial<DaemonAdminMetadata>
29
+ const pid = typeof candidate.pid === 'number' && Number.isFinite(candidate.pid) ? Math.trunc(candidate.pid) : null
30
+ const port = typeof candidate.port === 'number' && Number.isFinite(candidate.port) ? Math.trunc(candidate.port) : null
31
+ const token = typeof candidate.token === 'string' ? candidate.token.trim() : ''
32
+ if (!pid || !port || !token) return null
33
+ return {
34
+ pid,
35
+ port,
36
+ token,
37
+ launchedAt: typeof candidate.launchedAt === 'number' && Number.isFinite(candidate.launchedAt)
38
+ ? Math.trunc(candidate.launchedAt)
39
+ : Date.now(),
40
+ source: typeof candidate.source === 'string' ? candidate.source : null,
41
+ }
42
+ }
43
+
44
+ export function readDaemonAdminMetadata(): DaemonAdminMetadata | null {
45
+ try {
46
+ const raw = JSON.parse(fs.readFileSync(DAEMON_ADMIN_METADATA_PATH, 'utf8'))
47
+ return normalizeMetadata(raw)
48
+ } catch {
49
+ return null
50
+ }
51
+ }
52
+
53
+ export function writeDaemonAdminMetadata(metadata: DaemonAdminMetadata): void {
54
+ fs.mkdirSync(path.dirname(DAEMON_ADMIN_METADATA_PATH), { recursive: true })
55
+ fs.writeFileSync(DAEMON_ADMIN_METADATA_PATH, `${JSON.stringify(metadata, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
56
+ }
57
+
58
+ export function clearDaemonAdminMetadata(): void {
59
+ try {
60
+ fs.unlinkSync(DAEMON_ADMIN_METADATA_PATH)
61
+ } catch {
62
+ // Ignore missing metadata file.
63
+ }
64
+ }