@swarmclawai/swarmclaw 1.3.2 → 1.3.4
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 +9 -0
- package/package.json +1 -1
- package/src/components/connectors/connector-list.tsx +1 -1
- package/src/components/connectors/connector-sheet.tsx +1 -1
- package/src/lib/providers/cli-utils.ts +3 -4
- package/src/lib/providers/index.ts +12 -22
- package/src/lib/providers/openclaw.ts +1 -2
- package/src/lib/server/agents/subagent-swarm.ts +2 -7
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +2 -5
- package/src/lib/server/chat-execution/prompt-builder.ts +4 -6
- package/src/lib/server/connectors/connector-inbound.ts +13 -0
- package/src/lib/server/connectors/connector-service.ts +7 -5
- package/src/lib/server/connectors/openclaw.ts +1 -2
- package/src/lib/server/provider-health.ts +2 -7
- package/src/lib/server/storage.ts +1 -1
- package/src/types/connector.ts +1 -1
package/README.md
CHANGED
|
@@ -204,6 +204,15 @@ Read the full setup guide in [`SWARMDOCK.md`](./SWARMDOCK.md), browse the public
|
|
|
204
204
|
|
|
205
205
|
## Release Notes
|
|
206
206
|
|
|
207
|
+
### v1.3.4 Highlights
|
|
208
|
+
|
|
209
|
+
- **Bug fix — custom provider loading under Turbopack (#32)**: converted all CommonJS `require()` calls across the codebase to ES module imports, fixing "Unknown provider: custom-\<id\>" errors and other potential Turbopack compatibility issues. Affected modules: providers, provider health, subagent swarm, prompt builder, chat finalization, CLI utils, and OpenClaw connectors. Thanks to @psywolf85 for the initial fix.
|
|
210
|
+
|
|
211
|
+
### v1.3.3 Highlights
|
|
212
|
+
|
|
213
|
+
- **Bug fix — stale connector status after auto-restart (#31)**: connectors that auto-restart via the daemon health monitor now show "Starting" instead of a stale "Stopped" or "Error" status in the UI until the daemon reports runtime state. Added `starting` to the `ConnectorStatus` type and updated both the connector list and detail views.
|
|
214
|
+
- **Bug fix — stale credentialId after credential rotation (#30)**: when a provider credential is deleted and re-created, connector sessions now fall back to resolving any valid credential for the same provider instead of failing with "Missing credentials."
|
|
215
|
+
|
|
207
216
|
### v1.3.2 Highlights
|
|
208
217
|
|
|
209
218
|
- **Custom provider fix for standalone builds**: fixed `require('@/lib/server/storage')` path alias resolution failure that caused custom providers to silently break in standalone/npm-global installs with "a is not a function" errors. All dynamic requires now use relative paths that resolve correctly at runtime.
|
package/package.json
CHANGED
|
@@ -322,7 +322,7 @@ export function ConnectorList({ inSidebar }: { inSidebar?: boolean }) {
|
|
|
322
322
|
{meta.label}
|
|
323
323
|
</span>
|
|
324
324
|
<span className="text-[11px] text-text-3">
|
|
325
|
-
{isRunning ? 'Connected' : c.status === 'error' ? 'Error' : 'Stopped'}
|
|
325
|
+
{isRunning ? 'Connected' : c.status === 'error' ? 'Error' : c.status === 'starting' ? 'Starting' : 'Stopped'}
|
|
326
326
|
</span>
|
|
327
327
|
</div>
|
|
328
328
|
</div>
|
|
@@ -1270,7 +1270,7 @@ export function ConnectorSheet() {
|
|
|
1270
1270
|
runtimeConnector?.status === 'error' ? 'bg-red-400' : 'bg-white/20'
|
|
1271
1271
|
}`} />
|
|
1272
1272
|
{effectiveRunning ? (waAuthenticated ? 'Connected and listening' : 'Connecting...') :
|
|
1273
|
-
runtimeConnector?.status === 'error' ? 'Error — see below' : 'Not connected'}
|
|
1273
|
+
runtimeConnector?.status === 'error' ? 'Error — see below' : runtimeConnector?.status === 'starting' ? 'Starting...' : 'Not connected'}
|
|
1274
1274
|
</div>
|
|
1275
1275
|
</div>
|
|
1276
1276
|
{effectiveRunning ? (
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import fs from 'fs'
|
|
10
10
|
import os from 'os'
|
|
11
|
+
import { findBinaryOnPath } from '../server/session-tools/context'
|
|
11
12
|
import path from 'path'
|
|
12
13
|
import { spawnSync, type ChildProcess } from 'child_process'
|
|
13
14
|
import { log } from '../server/logger'
|
|
@@ -63,10 +64,8 @@ function getNvmBinaryPaths(name: string): string[] {
|
|
|
63
64
|
* then falls back to known paths + nvm paths.
|
|
64
65
|
*/
|
|
65
66
|
export function resolveCliBinary(name: string, extraPaths?: string[]): string | null {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const { findBinaryOnPath } = require('../server/session-tools/context')
|
|
69
|
-
const fromPath = findBinaryOnPath(name) as string | null
|
|
67
|
+
const fromPath = findBinaryOnPath(name)
|
|
68
|
+
|
|
70
69
|
if (fromPath) return fromPath
|
|
71
70
|
|
|
72
71
|
const paths = [
|
|
@@ -11,6 +11,8 @@ import { errorMessage, sleep, jitteredBackoff } from '@/lib/shared-utils'
|
|
|
11
11
|
import { classifyProviderError } from './error-classification'
|
|
12
12
|
import { log } from '@/lib/server/logger'
|
|
13
13
|
import type { ProviderInfo, ProviderConfig as CustomProviderConfig, ProviderType, ProviderId } from '../../types'
|
|
14
|
+
import { loadProviderConfigs, loadModelOverrides, loadStoredItem, loadCredentials, decryptKey } from '@/lib/server/storage'
|
|
15
|
+
import { getExtensionManager } from '@/lib/server/extensions'
|
|
14
16
|
|
|
15
17
|
const TAG = 'providers'
|
|
16
18
|
|
|
@@ -289,8 +291,6 @@ export const PROVIDERS: Record<string, BuiltinProviderConfig> = {
|
|
|
289
291
|
/** Merge built-in providers with custom providers from storage */
|
|
290
292
|
function getCustomProviders(): Record<string, CustomProviderConfig> {
|
|
291
293
|
try {
|
|
292
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
293
|
-
const { loadProviderConfigs } = require('../server/storage') as typeof import('@/lib/server/storage')
|
|
294
294
|
const configs = loadProviderConfigs() as Record<string, CustomProviderConfig>
|
|
295
295
|
return Object.fromEntries(
|
|
296
296
|
Object.entries(configs).filter(([, config]) => config?.type === 'custom'),
|
|
@@ -303,8 +303,6 @@ function getCustomProviders(): Record<string, CustomProviderConfig> {
|
|
|
303
303
|
|
|
304
304
|
function getModelOverrides(): Record<string, string[]> {
|
|
305
305
|
try {
|
|
306
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
307
|
-
const { loadModelOverrides } = require('../server/storage') as typeof import('@/lib/server/storage')
|
|
308
306
|
return loadModelOverrides()
|
|
309
307
|
} catch {
|
|
310
308
|
return {}
|
|
@@ -342,17 +340,15 @@ export function getProviderList(): ProviderInfo[] {
|
|
|
342
340
|
|
|
343
341
|
let extensionProviders: ProviderInfo[] = []
|
|
344
342
|
try {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
requiresEndpoint: Boolean(p.requiresEndpoint),
|
|
355
|
-
defaultEndpoint: p.defaultEndpoint as string | undefined,
|
|
343
|
+
extensionProviders = getExtensionManager().getProviders().map((p) => ({
|
|
344
|
+
id: p.id as ProviderId,
|
|
345
|
+
name: p.name,
|
|
346
|
+
models: p.models,
|
|
347
|
+
defaultModels: p.models,
|
|
348
|
+
supportsModelDiscovery: false,
|
|
349
|
+
requiresApiKey: p.requiresApiKey,
|
|
350
|
+
requiresEndpoint: p.requiresEndpoint,
|
|
351
|
+
defaultEndpoint: p.defaultEndpoint,
|
|
356
352
|
}))
|
|
357
353
|
} catch { /* ignore if running somewhere extensions aren't available */ }
|
|
358
354
|
|
|
@@ -391,8 +387,6 @@ export function getProvider(id: string): BuiltinProviderConfig | null {
|
|
|
391
387
|
// Fallback: direct single-item DB lookup for custom-* providers
|
|
392
388
|
if (id.startsWith('custom-') && !custom) {
|
|
393
389
|
try {
|
|
394
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
395
|
-
const { loadStoredItem } = require('../server/storage') as typeof import('@/lib/server/storage')
|
|
396
390
|
const directConfig = loadStoredItem('provider_configs', id) as CustomProviderConfig | null
|
|
397
391
|
if (directConfig?.type === 'custom' && directConfig.isEnabled) {
|
|
398
392
|
log.info(TAG, `Resolved custom provider '${id}' via direct DB lookup (batch load missed it)`)
|
|
@@ -405,10 +399,8 @@ export function getProvider(id: string): BuiltinProviderConfig | null {
|
|
|
405
399
|
|
|
406
400
|
// Check Extension Providers
|
|
407
401
|
try {
|
|
408
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
409
|
-
const { getExtensionManager } = require('../server/extensions')
|
|
410
402
|
const extensionProviders = getExtensionManager().getProviders()
|
|
411
|
-
const found = extensionProviders.find((p
|
|
403
|
+
const found = extensionProviders.find((p) => p.id === id)
|
|
412
404
|
if (found) {
|
|
413
405
|
return {
|
|
414
406
|
id: found.id as ProviderId,
|
|
@@ -455,8 +447,6 @@ export async function streamChatWithFailover(
|
|
|
455
447
|
let apiKey: string | null = opts.apiKey || null
|
|
456
448
|
if (credId && i > 0) {
|
|
457
449
|
// Need to decrypt fallback credential
|
|
458
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
459
|
-
const { loadCredentials, decryptKey } = require('../server/storage') as typeof import('@/lib/server/storage')
|
|
460
450
|
const creds = loadCredentials()
|
|
461
451
|
const cred = creds[credId]
|
|
462
452
|
if (cred?.encryptedKey) {
|
|
@@ -8,6 +8,7 @@ import type { Agent } from '@/types'
|
|
|
8
8
|
import { deriveOpenClawWsUrl } from '@/lib/openclaw/openclaw-endpoint'
|
|
9
9
|
import { normalizeOpenClawAgentId } from '@/lib/openclaw/openclaw-agent-id'
|
|
10
10
|
import { loadAgents } from '../server/storage'
|
|
11
|
+
import { getSharedDeviceToken } from '../server/openclaw/sync'
|
|
11
12
|
import {
|
|
12
13
|
resolveOpenClawGatewayAgentIdFromList,
|
|
13
14
|
type OpenClawGatewayAgentSummary,
|
|
@@ -74,8 +75,6 @@ function tryLoadIdentityFile(filePath: string): DeviceIdentity | null {
|
|
|
74
75
|
function loadOrCreateDeviceIdentity(): DeviceIdentity {
|
|
75
76
|
// 0. Check shared device token for cross-synced identity
|
|
76
77
|
try {
|
|
77
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
78
|
-
const { getSharedDeviceToken } = require('../server/openclaw/sync')
|
|
79
78
|
const sharedToken = getSharedDeviceToken()
|
|
80
79
|
if (sharedToken) {
|
|
81
80
|
// Shared token exists — the connector has already paired.
|
|
@@ -17,6 +17,7 @@ import { logActivity } from '@/lib/server/activity/activity-log'
|
|
|
17
17
|
import { createNotification } from '@/lib/server/create-notification'
|
|
18
18
|
import { notify } from '@/lib/server/ws-hub'
|
|
19
19
|
import { loadAgents } from '@/lib/server/agents/agent-repository'
|
|
20
|
+
import { upsertStoredItem, loadStoredItem, loadCollection } from '../storage'
|
|
20
21
|
import {
|
|
21
22
|
spawnSubagent,
|
|
22
23
|
type SubagentContext,
|
|
@@ -159,8 +160,6 @@ function notifySwarmChanged() {
|
|
|
159
160
|
|
|
160
161
|
function persistSwarmSnapshot(swarm: SwarmHandle): void {
|
|
161
162
|
try {
|
|
162
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
163
|
-
const { upsertStoredItem } = require('../storage')
|
|
164
163
|
upsertStoredItem('swarm_snapshots', swarm.swarmId, {
|
|
165
164
|
swarmId: swarm.swarmId,
|
|
166
165
|
parentSessionId: swarm.parentSessionId,
|
|
@@ -549,8 +548,6 @@ export function getSwarmSnapshot(swarmId: string): SwarmSnapshot | null {
|
|
|
549
548
|
if (swarm) return buildSwarmSnapshot(swarm)
|
|
550
549
|
// Fallback to persisted store for swarms from previous process lifetimes
|
|
551
550
|
try {
|
|
552
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
553
|
-
const { loadStoredItem } = require('../storage')
|
|
554
551
|
const persisted = loadStoredItem('swarm_snapshots', swarmId)
|
|
555
552
|
return persisted ? (persisted as SwarmSnapshot) : null
|
|
556
553
|
} catch { return null }
|
|
@@ -640,9 +637,7 @@ function buildSwarmSnapshot(swarm: SwarmHandle): SwarmSnapshot {
|
|
|
640
637
|
*/
|
|
641
638
|
export function restoreSwarmRegistry(): number {
|
|
642
639
|
try {
|
|
643
|
-
|
|
644
|
-
const { loadCollection, upsertStoredItem } = require('../storage')
|
|
645
|
-
const persisted = loadCollection('swarm_snapshots') as Record<string, SwarmSnapshot>
|
|
640
|
+
const persisted = loadCollection('swarm_snapshots') as unknown as Record<string, SwarmSnapshot>
|
|
646
641
|
let lost = 0
|
|
647
642
|
for (const [id, record] of Object.entries(persisted)) {
|
|
648
643
|
if (swarmRegistry.has(id)) continue
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Message, MessageToolEvent, SSEEvent, Session, UsageRecord } from '@/types'
|
|
2
|
+
import { sendConnectorMessage } from '../connectors/manager'
|
|
2
3
|
import { applyExactOutputContract, classifyExactOutputContract, type ExactOutputContract } from '@/lib/server/chat-execution/exact-output-contract'
|
|
3
4
|
import { stripMainLoopMetaForPersistence } from '@/lib/server/agents/main-agent-loop'
|
|
4
5
|
import { shouldSuppressHiddenControlText, stripHiddenControlTokens } from '@/lib/server/agents/assistant-control'
|
|
@@ -478,8 +479,6 @@ export async function finalizeChatTurn(params: {
|
|
|
478
479
|
&& heartbeatConfig.target !== 'none'
|
|
479
480
|
) {
|
|
480
481
|
try {
|
|
481
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
482
|
-
const { sendConnectorMessage } = require('../connectors/manager')
|
|
483
482
|
let connectorId: string | undefined
|
|
484
483
|
let channelId: string | undefined
|
|
485
484
|
if (heartbeatConfig.target === 'last') {
|
|
@@ -527,9 +526,7 @@ export async function finalizeChatTurn(params: {
|
|
|
527
526
|
: ''
|
|
528
527
|
if (!recentInbound && channelId) {
|
|
529
528
|
try {
|
|
530
|
-
|
|
531
|
-
const { sendConnectorMessage: sendMsg } = require('../connectors/manager')
|
|
532
|
-
sendMsg({ connectorId: connectorId || undefined, channelId, text: nextAssistantMessage.text }).catch((err: unknown) => {
|
|
529
|
+
sendConnectorMessage({ connectorId: connectorId || undefined, channelId, text: nextAssistantMessage.text }).catch((err: unknown) => {
|
|
533
530
|
log.warn('connector', 'Auto-route connector delivery failed', {
|
|
534
531
|
connectorId,
|
|
535
532
|
channelId,
|
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
collectCapabilityOperatingGuidance,
|
|
12
12
|
} from '@/lib/server/native-capabilities'
|
|
13
13
|
import { getExtensionManager } from '@/lib/server/extensions'
|
|
14
|
+
import { loadAgents } from '../storage'
|
|
15
|
+
import { resolveTeam } from '../agents/team-resolution'
|
|
14
16
|
import {
|
|
15
17
|
getEnabledToolPlanningView,
|
|
16
18
|
getToolsForCapability,
|
|
@@ -44,12 +46,8 @@ function buildExtensionCapabilityLines(enabledExtensions: string[], opts?: { del
|
|
|
44
46
|
// CLI team hint — if teammates run CLI providers, mention their strengths
|
|
45
47
|
if (opts.agentId) {
|
|
46
48
|
try {
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
50
|
-
const { resolveTeam } = require('../agents/team-resolution')
|
|
51
|
-
const agents = loadAgents() as Record<string, Record<string, unknown>>
|
|
52
|
-
const team = resolveTeam(opts.agentId, agents)
|
|
49
|
+
const agents = loadAgents()
|
|
50
|
+
const team = resolveTeam(opts.agentId, agents as Record<string, import('@/types').Agent>)
|
|
53
51
|
if (team.mode === 'team') {
|
|
54
52
|
const cliTeammates: string[] = []
|
|
55
53
|
const allMembers = [...(team.coordinator ? [team.coordinator] : []), ...team.peers, ...team.directReports]
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
selectChatroomRecipients,
|
|
29
29
|
} from '@/lib/server/chatrooms/chatroom-routing'
|
|
30
30
|
import { markProviderFailure, markProviderSuccess } from '../provider-health'
|
|
31
|
+
import { listCredentialIdsByProvider, resolveCredentialSecret } from '@/lib/server/credentials/credential-service'
|
|
31
32
|
import { buildIdentityContinuityContext } from '../identity-continuity'
|
|
32
33
|
import { buildRuntimeSkillPromptBlocks, resolveRuntimeSkills } from '@/lib/server/skills/runtime-skill-resolver'
|
|
33
34
|
import { getProvider } from '@/lib/providers'
|
|
@@ -1009,6 +1010,18 @@ async function routeMessage(connector: Connector, msg: InboundMessage): Promise<
|
|
|
1009
1010
|
}
|
|
1010
1011
|
}
|
|
1011
1012
|
|
|
1013
|
+
// Fallback: session credential was deleted — try any credential for this provider
|
|
1014
|
+
if (!apiKey && session.provider) {
|
|
1015
|
+
const providerCredentialIds = listCredentialIdsByProvider(session.provider)
|
|
1016
|
+
for (const id of providerCredentialIds) {
|
|
1017
|
+
const resolved = resolveCredentialSecret(id)
|
|
1018
|
+
if (resolved) {
|
|
1019
|
+
apiKey = resolved
|
|
1020
|
+
break
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1012
1025
|
// Build system prompt: [identity] \n\n [userPrompt] \n\n [soul] \n\n [systemPrompt]
|
|
1013
1026
|
const settings = loadSettings()
|
|
1014
1027
|
const promptParts: string[] = []
|
|
@@ -62,11 +62,13 @@ function persistConnector(connector: Connector): void {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function applyRuntimeFields(connector: Connector, runtime: DaemonConnectorRuntimeState | null): Connector {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
if (runtime?.status) {
|
|
66
|
+
connector.status = runtime.status
|
|
67
|
+
} else if (connector.isEnabled) {
|
|
68
|
+
connector.status = 'starting'
|
|
69
|
+
} else {
|
|
70
|
+
connector.status = connector.lastError ? 'error' : 'stopped'
|
|
71
|
+
}
|
|
70
72
|
|
|
71
73
|
if (connector.platform === 'whatsapp') {
|
|
72
74
|
connector.authenticated = runtime?.authenticated
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
type GatewayResponseFrame,
|
|
14
14
|
} from '../gateway/protocol'
|
|
15
15
|
import { log } from '@/lib/server/logger'
|
|
16
|
+
import { setSharedDeviceToken } from '../openclaw/sync'
|
|
16
17
|
|
|
17
18
|
const TAG = 'openclaw'
|
|
18
19
|
|
|
@@ -830,8 +831,6 @@ const openclaw: PlatformConnector = {
|
|
|
830
831
|
// Cross-sync device token for provider identity resolution
|
|
831
832
|
if (normalized) {
|
|
832
833
|
try {
|
|
833
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
834
|
-
const { setSharedDeviceToken } = require('../openclaw/sync')
|
|
835
834
|
setSharedDeviceToken(normalized)
|
|
836
835
|
} catch { /* openclaw-sync not available */ }
|
|
837
836
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from 'child_process'
|
|
2
2
|
import { errorMessage, hmrSingleton, jitteredBackoff } from '@/lib/shared-utils'
|
|
3
|
+
import { upsertStoredItem, loadCollection } from './storage'
|
|
3
4
|
|
|
4
5
|
type DelegateTool = 'delegate_to_claude_code' | 'delegate_to_codex_cli' | 'delegate_to_opencode_cli' | 'delegate_to_gemini_cli'
|
|
5
6
|
|
|
@@ -70,8 +71,6 @@ export function markProviderFailure(providerId: string, error: string, credentia
|
|
|
70
71
|
cooldownUntil: now + cooldownMsForFailures(failures),
|
|
71
72
|
})
|
|
72
73
|
try {
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
74
|
-
const { upsertStoredItem } = require('./storage')
|
|
75
74
|
upsertStoredItem('provider_health', key, states.get(key)!)
|
|
76
75
|
} catch {}
|
|
77
76
|
}
|
|
@@ -88,8 +87,6 @@ export function markProviderSuccess(providerId: string, credentialId?: string |
|
|
|
88
87
|
cooldownUntil: undefined,
|
|
89
88
|
})
|
|
90
89
|
try {
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
92
|
-
const { upsertStoredItem } = require('./storage')
|
|
93
90
|
upsertStoredItem('provider_health', key, states.get(key)!)
|
|
94
91
|
} catch {}
|
|
95
92
|
}
|
|
@@ -187,9 +184,7 @@ export function getProviderHealthSnapshot(): Record<string, ProviderHealthState
|
|
|
187
184
|
|
|
188
185
|
export function restoreProviderHealthState(): number {
|
|
189
186
|
try {
|
|
190
|
-
|
|
191
|
-
const { loadCollection } = require('./storage')
|
|
192
|
-
const persisted = loadCollection('provider_health') as Record<string, ProviderHealthState>
|
|
187
|
+
const persisted = loadCollection('provider_health') as unknown as Record<string, ProviderHealthState>
|
|
193
188
|
let restored = 0
|
|
194
189
|
for (const [id, record] of Object.entries(persisted)) {
|
|
195
190
|
if (states.has(id)) continue
|
|
@@ -242,7 +242,7 @@ function loadCollectionWithNormalizationState(table: string): {
|
|
|
242
242
|
return { result, normalizedCount }
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
function loadCollection(table: string): Record<string, StoredObject> {
|
|
245
|
+
export function loadCollection(table: string): Record<string, StoredObject> {
|
|
246
246
|
const { result, normalizedCount } = loadCollectionWithNormalizationState(table)
|
|
247
247
|
if (normalizedCount > 0) saveCollection(table, result)
|
|
248
248
|
return result
|
package/src/types/connector.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type ConnectorPlatform =
|
|
|
29
29
|
| 'webchat'
|
|
30
30
|
| 'mockmail'
|
|
31
31
|
| 'swarmdock'
|
|
32
|
-
export type ConnectorStatus = 'stopped' | 'running' | 'error'
|
|
32
|
+
export type ConnectorStatus = 'stopped' | 'running' | 'error' | 'starting'
|
|
33
33
|
|
|
34
34
|
export interface MessageSource {
|
|
35
35
|
platform: ConnectorPlatform
|