@lota-sdk/core 0.4.36 → 0.4.37
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lota-sdk/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.37",
|
|
4
4
|
"files": [
|
|
5
5
|
"src",
|
|
6
6
|
"infrastructure/schema"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@ai-sdk/provider": "^3.0.9",
|
|
33
33
|
"@chat-adapter/slack": "^4.26.0",
|
|
34
34
|
"@chat-adapter/state-ioredis": "^4.26.0",
|
|
35
|
-
"@lota-sdk/shared": "0.4.
|
|
35
|
+
"@lota-sdk/shared": "0.4.37",
|
|
36
36
|
"@mendable/firecrawl-js": "^4.20.0",
|
|
37
37
|
"@surrealdb/node": "^3.0.3",
|
|
38
38
|
"ai": "^6.0.170",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PlanFailureClass } from '@lota-sdk/shared'
|
|
1
2
|
import { Context, Schema, Effect, Layer } from 'effect'
|
|
2
3
|
|
|
3
4
|
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
@@ -39,6 +40,18 @@ function buildWakeDedupeKey(params: {
|
|
|
39
40
|
return `${params.organizationId}:${params.threadId}:${params.runId}:${params.nodeId}:${params.agentId}`
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
function classifyPlanTurnDispatchFailure(error: unknown): PlanFailureClass {
|
|
44
|
+
const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase()
|
|
45
|
+
if (message.includes('timeout')) {
|
|
46
|
+
return 'timeout_exceeded'
|
|
47
|
+
}
|
|
48
|
+
return 'non_recoverable_logic_error'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatPlanTurnDispatchError(error: unknown): string {
|
|
52
|
+
return error instanceof Error ? error.message : String(error)
|
|
53
|
+
}
|
|
54
|
+
|
|
42
55
|
class PlanAgentHeartbeatError extends Schema.TaggedErrorClass<PlanAgentHeartbeatError>()(
|
|
43
56
|
ERROR_TAGS.PlanAgentHeartbeatError,
|
|
44
57
|
{ operation: Schema.String, cause: Schema.Defect },
|
|
@@ -151,9 +164,27 @@ export function makePlanAgentHeartbeatService(deps: PlanAgentHeartbeatDeps) {
|
|
|
151
164
|
)
|
|
152
165
|
}
|
|
153
166
|
|
|
154
|
-
yield*
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
yield* threadTurnService.triggerPlanNodeTurn({ runId: params.runId, nodeId: params.nodeId }).pipe(
|
|
168
|
+
Effect.catch((cause) =>
|
|
169
|
+
heartbeatServiceEffect(
|
|
170
|
+
'block-node-on-plan-turn-failure',
|
|
171
|
+
planExecutorService.blockNodeOnDispatchFailure({
|
|
172
|
+
threadId: threadRef,
|
|
173
|
+
runId: params.runId,
|
|
174
|
+
nodeId: params.nodeId,
|
|
175
|
+
emittedBy: 'plan-agent-heartbeat',
|
|
176
|
+
message: formatPlanTurnDispatchError(cause),
|
|
177
|
+
failureClass: classifyPlanTurnDispatchFailure(cause),
|
|
178
|
+
}),
|
|
179
|
+
).pipe(
|
|
180
|
+
Effect.tap(() =>
|
|
181
|
+
Effect.sync(() => {
|
|
182
|
+
serverLogger.warn`Plan agent heartbeat blocked ${params.runId}/${params.nodeId} after plan-turn failure: ${formatPlanTurnDispatchError(cause)}`
|
|
183
|
+
}),
|
|
184
|
+
),
|
|
185
|
+
Effect.asVoid,
|
|
186
|
+
),
|
|
187
|
+
),
|
|
157
188
|
)
|
|
158
189
|
return true
|
|
159
190
|
}),
|
package/src/workers/bootstrap.ts
CHANGED
|
@@ -8,14 +8,13 @@ import {
|
|
|
8
8
|
makeAiGatewayService,
|
|
9
9
|
} from '../ai-gateway/ai-gateway'
|
|
10
10
|
import type { AiGatewayModels, RuntimeBridge } from '../ai-gateway/ai-gateway'
|
|
11
|
-
import { EmbeddingCacheLive } from '../ai/embedding-cache'
|
|
12
11
|
import { serverLogger } from '../config/logger'
|
|
13
12
|
import { connectWithStartupRetry, waitForDatabaseBootstrap } from '../db/startup'
|
|
14
13
|
import { buildWorkerInfrastructureLayer } from '../effect'
|
|
15
14
|
import { ERROR_TAGS } from '../effect/errors'
|
|
16
15
|
import { DatabaseServiceTag, RuntimeAdaptersServiceTag } from '../effect/services'
|
|
16
|
+
import { buildDomainServiceLayer } from '../runtime/domain-layer'
|
|
17
17
|
import { lotaRuntimeEnvConfig, parseLotaRuntimeConfig, parseWorkerBootstrapEnv } from '../runtime/runtime-config'
|
|
18
|
-
import { FirecrawlLive } from '../tools/firecrawl-client'
|
|
19
18
|
import { getErrorMessage } from '../utils/errors'
|
|
20
19
|
|
|
21
20
|
class SandboxedWorkerBootstrapError extends Schema.TaggedErrorClass<SandboxedWorkerBootstrapError>()(
|
|
@@ -103,11 +102,7 @@ function ensureSandboxedWorkerRuntimeConfigured(): Promise<WorkerManagedRuntime>
|
|
|
103
102
|
Layer.effect(AiGatewayModelsTag, Deferred.await(aiGatewayModelsDeferred)),
|
|
104
103
|
Layer.effect(RuntimeBridgeTag, Deferred.await(runtimeBridgeDeferred)),
|
|
105
104
|
)
|
|
106
|
-
const
|
|
107
|
-
const fullLayer = Layer.mergeAll(
|
|
108
|
-
layerWithBridge,
|
|
109
|
-
Layer.provide(Layer.mergeAll(EmbeddingCacheLive, FirecrawlLive), layerWithBridge),
|
|
110
|
-
)
|
|
105
|
+
const fullLayer = buildDomainServiceLayer(infrastructureLayer, bridgeLayer)
|
|
111
106
|
|
|
112
107
|
const managedRuntime = ManagedRuntime.make(fullLayer)
|
|
113
108
|
const runtimeBridge: RuntimeBridge = {
|
|
@@ -7,11 +7,12 @@ import { serverLogger } from '../config/logger'
|
|
|
7
7
|
import {
|
|
8
8
|
AgentConfigServiceTag,
|
|
9
9
|
DatabaseServiceTag,
|
|
10
|
+
RedisServiceTag,
|
|
10
11
|
RuntimeAdaptersServiceTag,
|
|
11
12
|
RuntimeConfigServiceTag,
|
|
12
13
|
} from '../effect/services'
|
|
14
|
+
import { makeOrganizationLearningQueueRuntime } from '../queues/organization-learning.queue'
|
|
13
15
|
import type { OrganizationLearningJob } from '../queues/organization-learning.queue'
|
|
14
|
-
import { LotaQueuesServiceTag } from '../queues/queues.service'
|
|
15
16
|
import { LearnedSkillServiceTag } from '../services/learned-skill.service'
|
|
16
17
|
import { MemoryServiceTag } from '../services/memory/memory.service'
|
|
17
18
|
import { QueueJobServiceTag } from '../services/queue-job.service'
|
|
@@ -28,7 +29,12 @@ const runtime = await initializeSandboxedWorkerRuntime()
|
|
|
28
29
|
const resolve = <I, T>(tag: Context.Key<I, T>): Promise<T> => runtime.runPromise(Effect.service(tag))
|
|
29
30
|
const agentConfig = await resolve(AgentConfigServiceTag)
|
|
30
31
|
const aiGatewayModels = await resolve(AiGatewayModelsTag)
|
|
31
|
-
const
|
|
32
|
+
const redis = await resolve(RedisServiceTag)
|
|
33
|
+
const organizationLearningQueueJobService = await resolve(QueueJobServiceTag)
|
|
34
|
+
const organizationLearningQueue = makeOrganizationLearningQueueRuntime({
|
|
35
|
+
connectionProvider: () => redis.getConnectionForBullMQ(),
|
|
36
|
+
queueJobService: organizationLearningQueueJobService,
|
|
37
|
+
})
|
|
32
38
|
const regularChatDigestServices: RegularChatDigestServices = {
|
|
33
39
|
agentConfig,
|
|
34
40
|
aiGatewayModels,
|
|
@@ -36,7 +42,7 @@ const regularChatDigestServices: RegularChatDigestServices = {
|
|
|
36
42
|
memoryService: await resolve(MemoryServiceTag),
|
|
37
43
|
socialChatHistoryService: await resolve(SocialChatHistoryServiceTag),
|
|
38
44
|
runtimeAdapters: await resolve(RuntimeAdaptersServiceTag),
|
|
39
|
-
organizationLearningQueue
|
|
45
|
+
organizationLearningQueue,
|
|
40
46
|
}
|
|
41
47
|
const workerRuntimeConfig = await resolve(RuntimeConfigServiceTag)
|
|
42
48
|
const skillExtractionServices: SkillExtractionServices = {
|
|
@@ -49,7 +55,6 @@ const skillExtractionServices: SkillExtractionServices = {
|
|
|
49
55
|
embeddingModel: workerRuntimeConfig.aiGateway.embeddingModel,
|
|
50
56
|
runPromise: (effect) => runtime.runPromise(effect),
|
|
51
57
|
}
|
|
52
|
-
const organizationLearningQueueJobService = await resolve(QueueJobServiceTag)
|
|
53
58
|
|
|
54
59
|
// One sandboxed worker handles both organization-learning branches so the
|
|
55
60
|
// queue can dispatch digest and skill jobs without separate worker images.
|