@swarmclawai/swarmclaw 1.2.4 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/bin/daemon-cmd.js +169 -0
- package/bin/server-cmd.js +3 -0
- package/bin/swarmclaw.js +11 -0
- package/package.json +17 -16
- package/src/app/api/agents/[id]/clone/route.ts +3 -32
- package/src/app/api/agents/[id]/route.ts +6 -158
- package/src/app/api/agents/[id]/status/route.ts +2 -3
- package/src/app/api/agents/[id]/thread/route.ts +4 -17
- package/src/app/api/agents/bulk/route.ts +5 -47
- package/src/app/api/agents/route.ts +5 -119
- package/src/app/api/agents/trash/route.ts +13 -24
- package/src/app/api/auth/route.ts +3 -9
- package/src/app/api/autonomy/estop/route.ts +5 -5
- package/src/app/api/chatrooms/[id]/chat/route.ts +11 -5
- package/src/app/api/chatrooms/[id]/route.ts +23 -2
- package/src/app/api/chatrooms/route.ts +13 -2
- package/src/app/api/chats/[id]/clear/route.ts +2 -13
- package/src/app/api/chats/[id]/deploy/route.ts +2 -3
- package/src/app/api/chats/[id]/edit-resend/route.ts +7 -13
- package/src/app/api/chats/[id]/mailbox/route.ts +6 -8
- package/src/app/api/chats/[id]/queue/route.ts +17 -64
- package/src/app/api/chats/[id]/retry/route.ts +4 -22
- package/src/app/api/chats/[id]/route.ts +10 -138
- package/src/app/api/chats/heartbeat/route.ts +2 -1
- package/src/app/api/chats/migrate-messages/route.ts +7 -0
- package/src/app/api/chats/route.ts +13 -134
- package/src/app/api/connectors/[id]/access/route.ts +12 -229
- package/src/app/api/connectors/[id]/doctor/route.ts +1 -1
- package/src/app/api/connectors/[id]/health/route.ts +12 -39
- package/src/app/api/connectors/[id]/route.ts +14 -122
- package/src/app/api/connectors/[id]/webhook/route.ts +1 -1
- package/src/app/api/connectors/doctor/route.ts +1 -1
- package/src/app/api/connectors/route.ts +12 -70
- package/src/app/api/credentials/[id]/route.ts +2 -4
- package/src/app/api/credentials/route.ts +10 -19
- package/src/app/api/daemon/health-check/route.ts +3 -4
- package/src/app/api/daemon/route.ts +10 -8
- package/src/app/api/documents/route.ts +11 -10
- package/src/app/api/external-agents/route.ts +3 -3
- package/src/app/api/gateways/[id]/health/route.ts +2 -3
- package/src/app/api/gateways/[id]/route.ts +7 -122
- package/src/app/api/gateways/route.ts +3 -103
- package/src/app/api/mcp-servers/[id]/tools/route.ts +5 -5
- package/src/app/api/openclaw/dashboard-url/route.ts +8 -16
- package/src/app/api/openclaw/directory/route.ts +2 -2
- package/src/app/api/openclaw/history/route.ts +3 -5
- package/src/app/api/providers/[id]/route.test.ts +49 -0
- package/src/app/api/providers/ollama/route.ts +6 -5
- package/src/app/api/schedules/[id]/route.ts +14 -108
- package/src/app/api/schedules/[id]/run/route.ts +6 -67
- package/src/app/api/schedules/route.ts +9 -51
- package/src/app/api/settings/route.ts +4 -3
- package/src/app/api/setup/check-provider/route.ts +23 -1
- package/src/app/api/setup/openclaw-device/route.ts +2 -2
- package/src/app/api/system/status/route.ts +2 -2
- package/src/app/api/tasks/[id]/route.ts +16 -202
- package/src/app/api/tasks/bulk/route.ts +5 -86
- package/src/app/api/tasks/metrics/route.ts +2 -1
- package/src/app/api/tasks/route.ts +11 -171
- package/src/app/api/upload/route.ts +1 -1
- package/src/app/api/uploads/[filename]/route.ts +1 -1
- package/src/app/api/uploads/route.ts +1 -1
- package/src/app/api/webhooks/[id]/history/route.ts +2 -2
- package/src/app/layout.tsx +9 -6
- package/src/app/protocols/page.tsx +71 -89
- package/src/app/tasks/page.tsx +32 -32
- package/src/cli/index.js +1 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-sheet.tsx +5 -5
- package/src/components/auth/setup-wizard/index.tsx +4 -4
- package/src/components/auth/setup-wizard/step-agents.tsx +1 -1
- package/src/components/auth/setup-wizard/step-connect.tsx +1 -1
- package/src/components/auth/setup-wizard/utils.ts +1 -1
- package/src/components/chatrooms/chatroom-sheet.tsx +16 -276
- package/src/components/connectors/connector-list.tsx +26 -40
- package/src/components/connectors/connector-sheet.tsx +95 -149
- package/src/components/gateways/gateway-sheet.tsx +61 -110
- package/src/components/layout/live-query-sync.tsx +121 -0
- package/src/components/protocols/structured-session-launcher.tsx +24 -45
- package/src/components/providers/app-query-provider.tsx +17 -0
- package/src/components/providers/provider-list.tsx +60 -61
- package/src/components/providers/provider-sheet.tsx +74 -56
- package/src/components/skills/skill-list.tsx +5 -18
- package/src/components/skills/skill-sheet.tsx +21 -20
- package/src/components/skills/skills-workspace.tsx +48 -87
- package/src/components/tasks/task-card.tsx +20 -13
- package/src/components/tasks/task-column.tsx +22 -7
- package/src/components/tasks/task-list.tsx +8 -11
- package/src/components/tasks/task-sheet.tsx +111 -103
- package/src/features/agents/queries.ts +20 -0
- package/src/features/chatrooms/queries.ts +20 -0
- package/src/features/chats/queries.ts +27 -0
- package/src/features/connectors/queries.ts +145 -0
- package/src/features/credentials/queries.ts +37 -0
- package/src/features/extensions/queries.ts +26 -0
- package/src/features/external-agents/queries.ts +36 -0
- package/src/features/gateways/queries.ts +274 -0
- package/src/features/missions/queries.ts +23 -0
- package/src/features/projects/queries.ts +20 -0
- package/src/features/protocols/queries.ts +149 -0
- package/src/features/providers/queries.ts +142 -0
- package/src/features/settings/queries.ts +20 -0
- package/src/features/skills/queries.ts +182 -0
- package/src/features/tasks/queries.ts +189 -0
- package/src/hooks/use-ws.ts +3 -2
- package/src/lib/app/api-client.ts +2 -2
- package/src/lib/providers/index.test.ts +108 -0
- package/src/lib/providers/index.ts +38 -15
- package/src/lib/query/client.ts +17 -0
- package/src/lib/server/agents/agent-runtime-config.ts +1 -1
- package/src/lib/server/agents/agent-service.ts +429 -0
- package/src/lib/server/agents/agent-thread-session.ts +6 -5
- package/src/lib/server/agents/autonomy-contract.ts +1 -4
- package/src/lib/server/agents/delegation-advisory.test.ts +206 -0
- package/src/lib/server/agents/delegation-advisory.ts +251 -0
- package/src/lib/server/agents/main-agent-loop.ts +98 -40
- package/src/lib/server/agents/subagent-runtime.ts +12 -0
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +20 -1
- package/src/lib/server/autonomy/supervisor-reflection.ts +39 -19
- package/src/lib/server/build-llm.ts +7 -15
- package/src/lib/server/capability-router.test.ts +70 -1
- package/src/lib/server/capability-router.ts +24 -99
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -15
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -4
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +77 -12
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +4 -4
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +2 -2
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +41 -17
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -2
- package/src/lib/server/chat-execution/chat-turn-tool-routing.test.ts +45 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +48 -17
- package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -1
- package/src/lib/server/chat-execution/direct-memory-intent.test.ts +9 -0
- package/src/lib/server/chat-execution/direct-memory-intent.ts +12 -2
- package/src/lib/server/chat-execution/message-classifier.test.ts +35 -23
- package/src/lib/server/chat-execution/message-classifier.ts +74 -32
- package/src/lib/server/chat-execution/prompt-builder.test.ts +29 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +37 -2
- package/src/lib/server/chat-execution/prompt-sections.test.ts +56 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +193 -0
- package/src/lib/server/chat-execution/stream-agent-chat.ts +63 -7
- package/src/lib/server/chat-execution/stream-continuation.test.ts +36 -0
- package/src/lib/server/chat-execution/stream-continuation.ts +28 -13
- package/src/lib/server/chatrooms/chatroom-agent-signals.ts +26 -18
- package/src/lib/server/chatrooms/chatroom-helpers.ts +19 -18
- package/src/lib/server/chatrooms/chatroom-repository.ts +16 -0
- package/src/lib/server/chatrooms/chatroom-routing.test.ts +96 -0
- package/src/lib/server/chatrooms/chatroom-routing.ts +207 -53
- package/src/lib/server/chatrooms/mailbox-utils.ts +4 -2
- package/src/lib/server/chatrooms/session-mailbox.ts +50 -40
- package/src/lib/server/chats/chat-session-service.ts +410 -0
- package/src/lib/server/connectors/access.ts +1 -1
- package/src/lib/server/connectors/commands.ts +7 -6
- package/src/lib/server/connectors/connector-inbound.ts +14 -7
- package/src/lib/server/connectors/connector-outbound.ts +16 -11
- package/src/lib/server/connectors/connector-service.ts +453 -0
- package/src/lib/server/connectors/delivery.ts +17 -12
- package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -14
- package/src/lib/server/connectors/media.ts +1 -1
- package/src/lib/server/connectors/response-media.ts +1 -1
- package/src/lib/server/connectors/session-consolidation.ts +11 -7
- package/src/lib/server/connectors/session.ts +9 -7
- package/src/lib/server/connectors/voice-note.ts +2 -1
- package/src/lib/server/context-manager.ts +20 -1
- package/src/lib/server/cost.ts +2 -3
- package/src/lib/server/credentials/credential-repository.ts +43 -4
- package/src/lib/server/credentials/credential-service.ts +112 -0
- package/src/lib/server/daemon/admin-metadata.ts +64 -0
- package/src/lib/server/daemon/controller.ts +577 -0
- package/src/lib/server/daemon/daemon-runtime.ts +352 -0
- package/src/lib/server/daemon/daemon-status-repository.ts +63 -0
- package/src/lib/server/daemon/types.ts +101 -0
- package/src/lib/server/embeddings.ts +3 -9
- package/src/lib/server/eval/agent-regression.ts +3 -2
- package/src/lib/server/eval/runner.ts +2 -2
- package/src/lib/server/execution-brief.test.ts +167 -0
- package/src/lib/server/execution-brief.ts +295 -0
- package/src/lib/server/execution-engine/chat-turn.ts +9 -0
- package/src/lib/server/execution-engine/import-boundary.test.ts +44 -0
- package/src/lib/server/execution-engine/index.ts +35 -0
- package/src/lib/server/execution-engine/task-attempt.ts +303 -0
- package/src/lib/server/execution-engine/types.ts +33 -0
- package/src/lib/server/gateways/gateway-profile-repository.ts +47 -3
- package/src/lib/server/gateways/gateway-profile-service.ts +200 -0
- package/src/lib/server/memory/session-archive-memory.ts +12 -10
- package/src/lib/server/messages/message-repository.ts +330 -0
- package/src/lib/server/missions/mission-service/core.ts +8 -6
- package/src/lib/server/openclaw/agent-resolver.ts +2 -3
- package/src/lib/server/openclaw/doctor.ts +1 -1
- package/src/lib/server/openclaw/gateway.test.ts +10 -1
- package/src/lib/server/openclaw/gateway.ts +5 -14
- package/src/lib/server/openclaw/health.ts +3 -11
- package/src/lib/server/openclaw/sync.ts +8 -6
- package/src/lib/server/persistence/storage-context.ts +3 -0
- package/src/lib/server/protocols/protocol-agent-turn.ts +25 -17
- package/src/lib/server/protocols/protocol-normalization.ts +1 -1
- package/src/lib/server/protocols/protocol-queries.ts +13 -7
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +16 -20
- package/src/lib/server/protocols/protocol-run-repository.ts +81 -0
- package/src/lib/server/protocols/protocol-step-processors.ts +23 -31
- package/src/lib/server/protocols/protocol-swarm.ts +8 -8
- package/src/lib/server/protocols/protocol-template-repository.ts +42 -0
- package/src/lib/server/protocols/protocol-templates.ts +4 -2
- package/src/lib/server/protocols/protocol-types.ts +10 -7
- package/src/lib/server/provider-endpoint.ts +7 -12
- package/src/lib/server/provider-model-discovery.ts +2 -11
- package/src/lib/server/query-expansion.ts +5 -6
- package/src/lib/server/run-context.test.ts +365 -0
- package/src/lib/server/run-context.ts +367 -0
- package/src/lib/server/runtime/heartbeat-service.ts +7 -5
- package/src/lib/server/runtime/queue/core.ts +61 -190
- package/src/lib/server/runtime/run-ledger.ts +8 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +2 -2
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +6 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +4 -0
- package/src/lib/server/schedules/schedule-route-service.ts +230 -0
- package/src/lib/server/service-result.ts +16 -0
- package/src/lib/server/session-note.ts +2 -3
- package/src/lib/server/session-reset-policy.ts +4 -3
- package/src/lib/server/session-tools/connector.ts +9 -6
- package/src/lib/server/session-tools/context-mgmt.ts +58 -9
- package/src/lib/server/session-tools/crud.ts +162 -10
- package/src/lib/server/session-tools/delegate.ts +1 -1
- package/src/lib/server/session-tools/manage-tasks.test.ts +152 -0
- package/src/lib/server/session-tools/memory.ts +6 -4
- package/src/lib/server/session-tools/session-info.test.ts +56 -0
- package/src/lib/server/session-tools/session-info.ts +119 -12
- package/src/lib/server/session-tools/skill-runtime.ts +3 -1
- package/src/lib/server/session-tools/skills.ts +15 -15
- package/src/lib/server/session-tools/subagent.test.ts +115 -1
- package/src/lib/server/session-tools/subagent.ts +125 -7
- package/src/lib/server/session-tools/team-context.ts +4 -3
- package/src/lib/server/session-tools/wallet.ts +0 -58
- package/src/lib/server/sessions/session-lineage.ts +55 -0
- package/src/lib/server/sessions/session-repository.ts +2 -2
- package/src/lib/server/skills/learned-skills.ts +24 -23
- package/src/lib/server/skills/runtime-skill-resolver.ts +2 -1
- package/src/lib/server/skills/skill-repository.ts +136 -13
- package/src/lib/server/skills/skill-suggestions.ts +25 -28
- package/src/lib/server/storage-normalization.test.ts +44 -267
- package/src/lib/server/storage-normalization.ts +75 -0
- package/src/lib/server/storage.ts +19 -0
- package/src/lib/server/structured-extract.ts +3 -14
- package/src/lib/server/tasks/task-followups.ts +16 -11
- package/src/lib/server/tasks/task-result.test.ts +25 -29
- package/src/lib/server/tasks/task-result.ts +5 -9
- package/src/lib/server/tasks/task-route-service.ts +449 -0
- package/src/lib/server/text-normalization.ts +41 -0
- package/src/lib/server/tool-planning.ts +6 -42
- package/src/lib/server/upload-path.ts +5 -0
- package/src/lib/server/working-state/extraction.ts +614 -0
- package/src/lib/server/working-state/normalization.ts +866 -0
- package/src/lib/server/working-state/prompt.ts +60 -0
- package/src/lib/server/working-state/repository.ts +38 -0
- package/src/lib/server/working-state/service.test.ts +253 -0
- package/src/lib/server/working-state/service.ts +293 -0
- package/src/lib/validation/schemas.ts +1 -0
- package/src/lib/ws-client.ts +3 -3
- package/src/stores/slices/task-slice.ts +1 -4
- package/src/stores/use-chatroom-store.ts +2 -2
- package/src/types/index.ts +277 -12
|
@@ -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
|
|
package/src/lib/server/cost.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
+
}
|