@lota-sdk/core 0.4.7 → 0.4.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.
- package/package.json +11 -12
- package/src/ai/embedding-cache.ts +94 -22
- package/src/ai-gateway/ai-gateway.ts +738 -223
- package/src/config/agent-defaults.ts +176 -75
- package/src/config/agent-types.ts +54 -4
- package/src/config/constants.ts +8 -2
- package/src/config/logger.ts +286 -19
- package/src/config/model-constants.ts +1 -0
- package/src/config/thread-defaults.ts +33 -21
- package/src/create-runtime.ts +725 -383
- package/src/db/base.service.ts +52 -28
- package/src/db/cursor-pagination.ts +71 -30
- package/src/db/memory-store.helpers.ts +4 -7
- package/src/db/memory-store.ts +856 -598
- package/src/db/memory.ts +398 -275
- package/src/db/record-id.ts +32 -10
- package/src/db/schema-fingerprint.ts +30 -12
- package/src/db/service-normalization.ts +255 -0
- package/src/db/service.ts +726 -761
- package/src/db/startup.ts +140 -66
- package/src/db/transaction-conflict.ts +15 -0
- package/src/effect/awaitable-effect.ts +87 -0
- package/src/effect/errors.ts +121 -0
- package/src/effect/helpers.ts +98 -0
- package/src/effect/index.ts +22 -0
- package/src/effect/layers.ts +228 -0
- package/src/effect/runtime-ref.ts +25 -0
- package/src/effect/runtime.ts +31 -0
- package/src/effect/services.ts +57 -0
- package/src/effect/zod.ts +43 -0
- package/src/embeddings/provider.ts +122 -71
- package/src/index.ts +46 -1
- package/src/openrouter/direct-provider.ts +29 -0
- package/src/queues/autonomous-job.queue.ts +130 -74
- package/src/queues/context-compaction.queue.ts +60 -15
- package/src/queues/delayed-node-promotion.queue.ts +52 -15
- package/src/queues/document-processor.queue.ts +52 -77
- package/src/queues/memory-consolidation.queue.ts +47 -32
- package/src/queues/organization-learning.queue.ts +13 -4
- package/src/queues/plan-agent-heartbeat.queue.ts +65 -21
- package/src/queues/plan-scheduler.queue.ts +107 -31
- package/src/queues/post-chat-memory.queue.ts +66 -24
- package/src/queues/queue-factory.ts +142 -52
- package/src/queues/standalone-worker.ts +39 -0
- package/src/queues/title-generation.queue.ts +54 -9
- package/src/redis/connection.ts +84 -32
- package/src/redis/index.ts +6 -8
- package/src/redis/org-memory-lock.ts +60 -27
- package/src/redis/redis-lease-lock.ts +200 -121
- package/src/redis/runtime-connection.ts +10 -0
- package/src/redis/stream-context.ts +84 -46
- package/src/runtime/agent-identity-overrides.ts +2 -2
- package/src/runtime/agent-runtime-policy.ts +4 -1
- package/src/runtime/agent-stream-helpers.ts +20 -9
- package/src/runtime/chat-run-orchestration.ts +102 -19
- package/src/runtime/chat-run-registry.ts +36 -2
- package/src/runtime/context-compaction/context-compaction-runtime.ts +107 -0
- package/src/runtime/{context-compaction.ts → context-compaction/context-compaction.ts} +114 -91
- package/src/runtime/execution-plan-visibility.ts +2 -2
- package/src/runtime/execution-plan.ts +42 -15
- package/src/runtime/graph-designer.ts +11 -7
- package/src/runtime/helper-model.ts +135 -48
- package/src/runtime/index.ts +7 -7
- package/src/runtime/indexed-repositories-policy.ts +3 -3
- package/src/runtime/{memory-block.ts → memory/memory-block.ts} +40 -36
- package/src/runtime/{memory-digest-policy.ts → memory/memory-digest-policy.ts} +1 -1
- package/src/runtime/{memory-pipeline.ts → memory/memory-pipeline.ts} +1 -1
- package/src/runtime/{memory-prompts-fact.ts → memory/memory-prompts-fact.ts} +2 -2
- package/src/runtime/{memory-scope.ts → memory/memory-scope.ts} +12 -6
- package/src/runtime/plugin-resolution.ts +144 -24
- package/src/runtime/plugin-types.ts +9 -1
- package/src/runtime/post-turn-side-effects.ts +197 -130
- package/src/runtime/retrieval-adapters.ts +38 -4
- package/src/runtime/runtime-config.ts +165 -61
- package/src/runtime/runtime-extensions.ts +21 -34
- package/src/runtime/social-chat/social-chat-agent-runner.ts +157 -0
- package/src/runtime/{social-chat-history.ts → social-chat/social-chat-history.ts} +42 -20
- package/src/runtime/social-chat/social-chat.ts +594 -0
- package/src/runtime/specialist-runner.ts +36 -10
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +427 -0
- package/src/runtime/{team-consultation-prompts.ts → team-consultation/team-consultation-prompts.ts} +6 -2
- package/src/runtime/thread-chat-helpers.ts +2 -2
- package/src/runtime/thread-plan-turn.ts +2 -1
- package/src/runtime/thread-turn-context.ts +172 -94
- package/src/runtime/turn-lifecycle.ts +93 -27
- package/src/services/agent-activity.service.ts +287 -203
- package/src/services/agent-executor.service.ts +329 -217
- package/src/services/artifact.service.ts +225 -148
- package/src/services/attachment.service.ts +137 -115
- package/src/services/autonomous-job.service.ts +888 -491
- package/src/services/chat-run-registry.service.ts +11 -1
- package/src/services/context-compaction.service.ts +136 -86
- package/src/services/document-chunk.service.ts +162 -90
- package/src/services/execution-plan/execution-plan-approval.ts +26 -0
- package/src/services/execution-plan/execution-plan-context.ts +29 -0
- package/src/services/execution-plan/execution-plan-graph.ts +256 -0
- package/src/services/execution-plan/execution-plan-schedule.ts +84 -0
- package/src/services/execution-plan/execution-plan-spec.ts +75 -0
- package/src/services/execution-plan/execution-plan.service.ts +1041 -0
- package/src/services/feedback-loop.service.ts +132 -76
- package/src/services/global-orchestrator.service.ts +80 -170
- package/src/services/graph-full-routing.ts +182 -0
- package/src/services/index.ts +18 -20
- package/src/services/institutional-memory.service.ts +220 -123
- package/src/services/learned-skill.service.ts +364 -259
- package/src/services/memory/memory-conversation.ts +95 -0
- package/src/services/memory/memory-org-memory.ts +39 -0
- package/src/services/memory/memory-preseeded.ts +80 -0
- package/src/services/memory/memory-rerank.ts +297 -0
- package/src/services/{memory-utils.ts → memory/memory-utils.ts} +5 -5
- package/src/services/memory/memory.service.ts +692 -0
- package/src/services/memory/rerank.service.ts +209 -0
- package/src/services/monitoring-window.service.ts +92 -70
- package/src/services/mutating-approval.service.ts +62 -53
- package/src/services/node-workspace.service.ts +141 -98
- package/src/services/notification.service.ts +17 -16
- package/src/services/organization-member.service.ts +120 -66
- package/src/services/organization.service.ts +144 -51
- package/src/services/ownership-dispatcher.service.ts +415 -264
- package/src/services/plan/plan-agent-heartbeat.service.ts +234 -0
- package/src/services/plan/plan-agent-query.service.ts +322 -0
- package/src/services/plan/plan-approval.service.ts +102 -0
- package/src/services/plan/plan-artifact.service.ts +60 -0
- package/src/services/plan/plan-builder.service.ts +76 -0
- package/src/services/plan/plan-checkpoint.service.ts +103 -0
- package/src/services/{plan-compiler.service.ts → plan/plan-compiler.service.ts} +26 -9
- package/src/services/plan/plan-completion-side-effects.ts +175 -0
- package/src/services/plan/plan-coordination.service.ts +181 -0
- package/src/services/plan/plan-cycle.service.ts +398 -0
- package/src/services/plan/plan-deadline.service.ts +547 -0
- package/src/services/plan/plan-event-delivery.service.ts +261 -0
- package/src/services/plan/plan-executor-context.ts +35 -0
- package/src/services/plan/plan-executor-graph.ts +475 -0
- package/src/services/plan/plan-executor-helpers.ts +322 -0
- package/src/services/plan/plan-executor-persistence.ts +209 -0
- package/src/services/plan/plan-executor.service.ts +1654 -0
- package/src/services/{plan-helpers.ts → plan/plan-helpers.ts} +1 -1
- package/src/services/{plan-run-data.ts → plan/plan-run-data.ts} +4 -4
- package/src/services/plan/plan-run-serialization.ts +15 -0
- package/src/services/plan/plan-run.service.ts +644 -0
- package/src/services/plan/plan-scheduler.service.ts +385 -0
- package/src/services/plan/plan-template.service.ts +224 -0
- package/src/services/plan/plan-transaction-events.ts +33 -0
- package/src/services/plan/plan-validator.service.ts +907 -0
- package/src/services/plan/plan-workspace.service.ts +125 -0
- package/src/services/plugin-executor.service.ts +97 -68
- package/src/services/quality-metrics.service.ts +112 -94
- package/src/services/queue-job.service.ts +296 -230
- package/src/services/recent-activity-title.service.ts +65 -36
- package/src/services/recent-activity.service.ts +274 -259
- package/src/services/skill-resolver.service.ts +38 -12
- package/src/services/social-chat-history.service.ts +176 -125
- package/src/services/system-executor.service.ts +91 -61
- package/src/services/thread/thread-active-run.ts +203 -0
- package/src/services/thread/thread-bootstrap.ts +369 -0
- package/src/services/thread/thread-listing.ts +198 -0
- package/src/services/thread/thread-memory-block.ts +117 -0
- package/src/services/thread/thread-message.service.ts +363 -0
- package/src/services/thread/thread-record-store.ts +155 -0
- package/src/services/thread/thread-title.service.ts +74 -0
- package/src/services/thread/thread-turn-execution.ts +280 -0
- package/src/services/thread/thread-turn-message-context.ts +73 -0
- package/src/services/thread/thread-turn-preparation.service.ts +1146 -0
- package/src/services/thread/thread-turn-streaming.ts +402 -0
- package/src/services/thread/thread-turn-tracing.ts +35 -0
- package/src/services/thread/thread-turn.ts +343 -0
- package/src/services/thread/thread.service.ts +335 -0
- package/src/services/user.service.ts +82 -32
- package/src/services/write-intent-validator.service.ts +63 -51
- package/src/storage/attachment-parser.ts +69 -27
- package/src/storage/attachment-storage.service.ts +331 -275
- package/src/storage/generated-document-storage.service.ts +66 -34
- package/src/system-agents/agent-result.ts +3 -1
- package/src/system-agents/context-compaction.agent.ts +2 -2
- package/src/system-agents/delegated-agent-factory.ts +159 -90
- package/src/system-agents/memory-reranker.agent.ts +2 -2
- package/src/system-agents/memory.agent.ts +2 -2
- package/src/system-agents/recent-activity-title-refiner.agent.ts +2 -2
- package/src/system-agents/regular-chat-memory-digest.agent.ts +2 -2
- package/src/system-agents/skill-extractor.agent.ts +2 -2
- package/src/system-agents/skill-manager.agent.ts +2 -2
- package/src/system-agents/thread-router.agent.ts +157 -113
- package/src/system-agents/title-generator.agent.ts +2 -2
- package/src/tools/execution-plan.tool.ts +220 -161
- package/src/tools/fetch-webpage.tool.ts +21 -17
- package/src/tools/firecrawl-client.ts +16 -6
- package/src/tools/index.ts +1 -0
- package/src/tools/memory-block.tool.ts +14 -6
- package/src/tools/plan-approval.tool.ts +49 -47
- package/src/tools/read-file-parts.tool.ts +44 -33
- package/src/tools/remember-memory.tool.ts +65 -45
- package/src/tools/search-web.tool.ts +26 -22
- package/src/tools/search.tool.ts +41 -29
- package/src/tools/team-think.tool.ts +124 -83
- package/src/tools/user-questions.tool.ts +4 -3
- package/src/tools/web-tool-shared.ts +6 -0
- package/src/utils/async.ts +17 -23
- package/src/utils/crypto.ts +21 -0
- package/src/utils/date-time.ts +40 -1
- package/src/utils/errors.ts +95 -16
- package/src/utils/hono-error-handler.ts +24 -39
- package/src/utils/index.ts +2 -1
- package/src/utils/null-proto-record.ts +41 -0
- package/src/utils/sse-keepalive.ts +124 -21
- package/src/workers/bootstrap.ts +186 -51
- package/src/workers/memory-consolidation.worker.ts +325 -237
- package/src/workers/organization-learning.worker.ts +50 -16
- package/src/workers/regular-chat-memory-digest.helpers.ts +28 -27
- package/src/workers/regular-chat-memory-digest.runner.ts +175 -114
- package/src/workers/skill-extraction.runner.ts +176 -93
- package/src/workers/utils/file-section-chunker.ts +8 -10
- package/src/workers/utils/repo-structure-extractor.ts +349 -260
- package/src/workers/utils/repomix-file-sections.ts +2 -2
- package/src/workers/utils/thread-message-query.ts +97 -38
- package/src/workers/worker-utils.ts +56 -31
- package/src/config/debug-logger.ts +0 -47
- package/src/redis/connection-accessor.ts +0 -26
- package/src/runtime/context-compaction-runtime.ts +0 -87
- package/src/runtime/social-chat-agent-runner.ts +0 -118
- package/src/runtime/social-chat.ts +0 -516
- package/src/runtime/team-consultation-orchestrator.ts +0 -272
- package/src/services/adaptive-playbook.service.ts +0 -152
- package/src/services/artifact-provenance.service.ts +0 -172
- package/src/services/chat-attachments.service.ts +0 -17
- package/src/services/context-compaction-runtime.singleton.ts +0 -13
- package/src/services/execution-plan.service.ts +0 -1118
- package/src/services/memory.service.ts +0 -844
- package/src/services/plan-agent-heartbeat.service.ts +0 -136
- package/src/services/plan-agent-query.service.ts +0 -267
- package/src/services/plan-approval.service.ts +0 -83
- package/src/services/plan-artifact.service.ts +0 -50
- package/src/services/plan-builder.service.ts +0 -67
- package/src/services/plan-checkpoint.service.ts +0 -81
- package/src/services/plan-completion-side-effects.ts +0 -80
- package/src/services/plan-coordination.service.ts +0 -157
- package/src/services/plan-cycle.service.ts +0 -284
- package/src/services/plan-deadline.service.ts +0 -430
- package/src/services/plan-event-delivery.service.ts +0 -166
- package/src/services/plan-executor.service.ts +0 -1950
- package/src/services/plan-run.service.ts +0 -515
- package/src/services/plan-scheduler.service.ts +0 -240
- package/src/services/plan-template.service.ts +0 -177
- package/src/services/plan-validator.service.ts +0 -818
- package/src/services/plan-workspace.service.ts +0 -83
- package/src/services/thread-message.service.ts +0 -275
- package/src/services/thread-plan-registry.service.ts +0 -22
- package/src/services/thread-title.service.ts +0 -39
- package/src/services/thread-turn-preparation.service.ts +0 -1147
- package/src/services/thread-turn.ts +0 -172
- package/src/services/thread.service.ts +0 -869
- package/src/utils/env.ts +0 -8
- /package/src/runtime/{context-compaction-constants.ts → context-compaction/context-compaction-constants.ts} +0 -0
- /package/src/runtime/{memory-format.ts → memory/memory-format.ts} +0 -0
- /package/src/runtime/{memory-prompts-parse.ts → memory/memory-prompts-parse.ts} +0 -0
- /package/src/runtime/{memory-prompts-update.ts → memory/memory-prompts-update.ts} +0 -0
- /package/src/runtime/{social-chat-prompts.ts → social-chat/social-chat-prompts.ts} +0 -0
- /package/src/services/{plan-node-spec.ts → plan/plan-node-spec.ts} +0 -0
- /package/src/services/{thread-constants.ts → thread/thread-constants.ts} +0 -0
- /package/src/services/{thread.types.ts → thread/thread.types.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -6,10 +6,55 @@ export * from './db'
|
|
|
6
6
|
export * from './document'
|
|
7
7
|
export * from './queues'
|
|
8
8
|
export * from './redis'
|
|
9
|
-
export * from './runtime
|
|
9
|
+
export * from './runtime'
|
|
10
10
|
export * from './services'
|
|
11
11
|
export * from './storage'
|
|
12
12
|
export * from './system-agents'
|
|
13
13
|
export * from './tools'
|
|
14
14
|
export * from './utils'
|
|
15
15
|
export * from './workers'
|
|
16
|
+
export { Effect } from 'effect'
|
|
17
|
+
export {
|
|
18
|
+
AgentConfigLive,
|
|
19
|
+
AgentFactoryLive,
|
|
20
|
+
AppLoggerTag,
|
|
21
|
+
AppLoggerLive,
|
|
22
|
+
EffectBadRequestError,
|
|
23
|
+
clearLotaSdkRuntime,
|
|
24
|
+
ConfigurationError,
|
|
25
|
+
ConflictError,
|
|
26
|
+
DatabaseError,
|
|
27
|
+
DatabaseLive,
|
|
28
|
+
DatabaseServiceTag as EffectDatabaseService,
|
|
29
|
+
EffectNotFoundError,
|
|
30
|
+
EffectThreadTurnError,
|
|
31
|
+
EffectValidationError,
|
|
32
|
+
getLotaSdkRuntime,
|
|
33
|
+
isEffectError,
|
|
34
|
+
LockAcquisitionError,
|
|
35
|
+
LockLostError,
|
|
36
|
+
ActiveThreadRunConflictError,
|
|
37
|
+
RedisError,
|
|
38
|
+
RedisLive,
|
|
39
|
+
RedisServiceTag as EffectRedisService,
|
|
40
|
+
RuntimeAdaptersServiceTag,
|
|
41
|
+
RuntimeConfigLive,
|
|
42
|
+
RuntimeConfigServiceTag,
|
|
43
|
+
RuntimeExtensionsLive,
|
|
44
|
+
RuntimeWorkerExtensionsServiceTag,
|
|
45
|
+
setLotaSdkRuntime,
|
|
46
|
+
ThreadConfigLive,
|
|
47
|
+
ThreadConfigServiceTag,
|
|
48
|
+
TimeoutError,
|
|
49
|
+
ToolProvidersServiceTag,
|
|
50
|
+
TurnHooksServiceTag,
|
|
51
|
+
toAwaitableEffect,
|
|
52
|
+
toAwaitableService,
|
|
53
|
+
summarizeZodIssues,
|
|
54
|
+
toValidationError,
|
|
55
|
+
toValidationIssues,
|
|
56
|
+
zodParse,
|
|
57
|
+
} from './effect'
|
|
58
|
+
export { AppError, BadRequestError, NotFoundError } from './utils'
|
|
59
|
+
export type { AppErrorLike, AppErrorResponse } from './utils'
|
|
60
|
+
export type { EffectError, ValidationIssue } from './effect'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createOpenAI } from '@ai-sdk/openai'
|
|
2
|
+
|
|
3
|
+
import { ConfigurationError } from '../effect/errors'
|
|
4
|
+
|
|
5
|
+
const DIRECT_OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1' as const
|
|
6
|
+
const OPENROUTER_MODEL_PREFIX = 'openrouter/' as const
|
|
7
|
+
|
|
8
|
+
export function resolveOpenRouterApiKey(openRouterApiKey: string | undefined): string {
|
|
9
|
+
const key = openRouterApiKey?.trim()
|
|
10
|
+
if (key) return key
|
|
11
|
+
|
|
12
|
+
throw new ConfigurationError({
|
|
13
|
+
message: 'Missing OpenRouter API key. Configure createLotaRuntime({ aiGateway: { openRouterApiKey } }).',
|
|
14
|
+
key: 'aiGateway.openRouterApiKey',
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function normalizeDirectOpenRouterModelId(modelId: string): string {
|
|
19
|
+
const normalized = modelId.trim()
|
|
20
|
+
if (!normalized) {
|
|
21
|
+
throw new ConfigurationError({ message: 'OpenRouter model id is required.', key: 'openRouterModelId' })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return normalized.startsWith(OPENROUTER_MODEL_PREFIX) ? normalized.slice(OPENROUTER_MODEL_PREFIX.length) : normalized
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getDirectOpenRouterProvider(openRouterApiKey?: string) {
|
|
28
|
+
return createOpenAI({ baseURL: DIRECT_OPENROUTER_BASE_URL, apiKey: resolveOpenRouterApiKey(openRouterApiKey) })
|
|
29
|
+
}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { AutonomousJobSchedule } from '@lota-sdk/shared'
|
|
2
2
|
import type { Job } from 'bullmq'
|
|
3
|
+
import { Effect } from 'effect'
|
|
4
|
+
import type { Context } from 'effect'
|
|
5
|
+
import type IORedis from 'ioredis'
|
|
3
6
|
|
|
4
7
|
import { serverLogger } from '../config/logger'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
+
import { ConfigurationError } from '../effect/errors'
|
|
9
|
+
import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
|
|
10
|
+
import { AutonomousJobServiceTag } from '../services/autonomous-job.service'
|
|
8
11
|
import { buildAutonomousAtJobId } from '../utils/autonomous-job-ids'
|
|
9
12
|
import type { WorkerHandle } from '../workers/worker-utils'
|
|
10
|
-
import { DEFAULT_JOB_RETENTION } from '../workers/worker-utils'
|
|
13
|
+
import { DEFAULT_JOB_RETENTION, getQueueJobService } from '../workers/worker-utils'
|
|
11
14
|
import { createQueueFactory } from './queue-factory'
|
|
15
|
+
import { runStandaloneQueueWorker } from './standalone-worker'
|
|
12
16
|
|
|
13
17
|
export interface AutonomousJobQueuePayload {
|
|
14
18
|
autonomousJobId: string
|
|
@@ -18,17 +22,29 @@ export interface AutonomousJobQueuePayload {
|
|
|
18
22
|
|
|
19
23
|
export const AUTONOMOUS_JOB_QUEUE = 'autonomous-job'
|
|
20
24
|
|
|
25
|
+
interface AutonomousJobQueueDeps {
|
|
26
|
+
databaseService: Context.Service.Shape<typeof DatabaseServiceTag>
|
|
27
|
+
autonomousJobService: Context.Service.Shape<typeof AutonomousJobServiceTag>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let _deps: AutonomousJobQueueDeps | null = null
|
|
31
|
+
function getDeps(): AutonomousJobQueueDeps {
|
|
32
|
+
if (!_deps)
|
|
33
|
+
throw new ConfigurationError({
|
|
34
|
+
message: 'Autonomous job queue is not configured. Initialize the runtime before starting the worker.',
|
|
35
|
+
key: 'queue-deps',
|
|
36
|
+
})
|
|
37
|
+
return _deps
|
|
38
|
+
}
|
|
39
|
+
|
|
21
40
|
const DEFAULT_AUTONOMOUS_JOB_OPTIONS = {
|
|
22
41
|
...DEFAULT_JOB_RETENTION,
|
|
23
42
|
attempts: 3,
|
|
24
43
|
backoff: { type: 'exponential', delay: 5_000 },
|
|
25
44
|
} as const
|
|
26
45
|
|
|
27
|
-
|
|
28
|
-
job
|
|
29
|
-
): Promise<{ status: string; summary?: string }> {
|
|
30
|
-
await databaseService.connect()
|
|
31
|
-
return autonomousJobService.executeQueuedRun(job)
|
|
46
|
+
function processAutonomousJob(job: Job<AutonomousJobQueuePayload>): Promise<{ status: string; summary?: string }> {
|
|
47
|
+
return Effect.runPromise(getDeps().autonomousJobService.executeQueuedRun(job))
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
const autonomousJobQueue = createQueueFactory<AutonomousJobQueuePayload>({
|
|
@@ -37,6 +53,7 @@ const autonomousJobQueue = createQueueFactory<AutonomousJobQueuePayload>({
|
|
|
37
53
|
jobName: 'run-autonomous-job',
|
|
38
54
|
concurrency: 2,
|
|
39
55
|
defaultJobOptions: DEFAULT_AUTONOMOUS_JOB_OPTIONS,
|
|
56
|
+
prepare: () => getDeps().databaseService.connect(),
|
|
40
57
|
processor: processAutonomousJob,
|
|
41
58
|
})
|
|
42
59
|
|
|
@@ -44,91 +61,130 @@ function buildAutonomousSchedulerId(autonomousJobId: string): string {
|
|
|
44
61
|
return `autonomous:${autonomousJobId}`
|
|
45
62
|
}
|
|
46
63
|
|
|
47
|
-
export
|
|
64
|
+
export function enqueueAutonomousJobRun(params: {
|
|
48
65
|
payload: AutonomousJobQueuePayload
|
|
49
66
|
delayMs?: number
|
|
50
67
|
jobId?: string
|
|
51
68
|
}): Promise<{ bullmqJobId: string; queueJobId?: string }> {
|
|
52
|
-
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
return Effect.runPromise(
|
|
70
|
+
Effect.gen(function* () {
|
|
71
|
+
const queuedJob = yield* Effect.tryPromise(() =>
|
|
72
|
+
autonomousJobQueue
|
|
73
|
+
.getQueue()
|
|
74
|
+
.add('run-autonomous-job', params.payload, {
|
|
75
|
+
...(typeof params.delayMs === 'number' ? { delay: Math.max(0, params.delayMs) } : {}),
|
|
76
|
+
...(params.jobId ? { jobId: params.jobId } : {}),
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const bullmqJobId = String(queuedJob.id)
|
|
81
|
+
const queueJobId = yield* Effect.catch(
|
|
82
|
+
getQueueJobService().recordEnqueued({
|
|
83
|
+
queueName: AUTONOMOUS_JOB_QUEUE,
|
|
84
|
+
id: queuedJob.id,
|
|
85
|
+
name: queuedJob.name,
|
|
86
|
+
data: queuedJob.data,
|
|
87
|
+
opts: queuedJob.opts,
|
|
88
|
+
attemptsMade: queuedJob.attemptsMade,
|
|
89
|
+
timestamp: queuedJob.timestamp,
|
|
90
|
+
}),
|
|
91
|
+
(error) =>
|
|
92
|
+
Effect.sync(() => {
|
|
93
|
+
serverLogger.error`Failed to persist queued job metadata (queue=${AUTONOMOUS_JOB_QUEUE}, job=${queuedJob.id}): ${error}`
|
|
94
|
+
return undefined
|
|
95
|
+
}),
|
|
96
|
+
)
|
|
97
|
+
return { bullmqJobId, queueJobId }
|
|
98
|
+
}),
|
|
99
|
+
)
|
|
77
100
|
}
|
|
78
101
|
|
|
79
|
-
export
|
|
102
|
+
export function upsertAutonomousJobScheduler(params: {
|
|
80
103
|
autonomousJobId: string
|
|
81
104
|
schedule: Extract<AutonomousJobSchedule, { kind: 'cron' | 'every' }>
|
|
82
105
|
}): Promise<void> {
|
|
83
106
|
const repeatOpts =
|
|
84
107
|
params.schedule.kind === 'cron' ? { pattern: params.schedule.cron } : { every: params.schedule.intervalMs }
|
|
85
|
-
|
|
86
|
-
.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
return Effect.runPromise(
|
|
109
|
+
Effect.gen(function* () {
|
|
110
|
+
const queuedJob = yield* Effect.tryPromise(() =>
|
|
111
|
+
autonomousJobQueue
|
|
112
|
+
.getQueue()
|
|
113
|
+
.upsertJobScheduler(buildAutonomousSchedulerId(params.autonomousJobId), repeatOpts, {
|
|
114
|
+
name: 'run-autonomous-job',
|
|
115
|
+
data: { autonomousJobId: params.autonomousJobId, trigger: 'scheduled' },
|
|
116
|
+
opts: DEFAULT_AUTONOMOUS_JOB_OPTIONS,
|
|
117
|
+
}),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
yield* Effect.catch(
|
|
121
|
+
getQueueJobService().recordEnqueued({
|
|
122
|
+
queueName: AUTONOMOUS_JOB_QUEUE,
|
|
123
|
+
id: queuedJob.id,
|
|
124
|
+
name: queuedJob.name,
|
|
125
|
+
data: queuedJob.data,
|
|
126
|
+
opts: queuedJob.opts,
|
|
127
|
+
attemptsMade: queuedJob.attemptsMade,
|
|
128
|
+
timestamp: queuedJob.timestamp,
|
|
129
|
+
}),
|
|
130
|
+
(error) =>
|
|
131
|
+
Effect.sync(() => {
|
|
132
|
+
serverLogger.error`Failed to persist queued job metadata (queue=${AUTONOMOUS_JOB_QUEUE}, job=${queuedJob.id}): ${error}`
|
|
133
|
+
}),
|
|
134
|
+
)
|
|
135
|
+
}),
|
|
136
|
+
)
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
export
|
|
109
|
-
|
|
139
|
+
export function removeAutonomousJobScheduler(autonomousJobId: string): Promise<void> {
|
|
140
|
+
return Effect.runPromise(
|
|
141
|
+
Effect.asVoid(
|
|
142
|
+
Effect.tryPromise(() =>
|
|
143
|
+
autonomousJobQueue.getQueue().removeJobScheduler(buildAutonomousSchedulerId(autonomousJobId)),
|
|
144
|
+
),
|
|
145
|
+
),
|
|
146
|
+
)
|
|
110
147
|
}
|
|
111
148
|
|
|
112
|
-
export
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
149
|
+
export function removeAutonomousAtJob(autonomousJobId: string): Promise<void> {
|
|
150
|
+
return Effect.runPromise(
|
|
151
|
+
Effect.catch(
|
|
152
|
+
Effect.asVoid(
|
|
153
|
+
Effect.tryPromise(() => autonomousJobQueue.getQueue().remove(buildAutonomousAtJobId(autonomousJobId))),
|
|
154
|
+
),
|
|
155
|
+
() => Effect.void,
|
|
156
|
+
),
|
|
157
|
+
)
|
|
118
158
|
}
|
|
119
159
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
160
|
+
interface AutonomousJobWorkerOptions {
|
|
161
|
+
registerSignals?: boolean
|
|
162
|
+
connectionProvider: () => IORedis
|
|
163
|
+
deps: AutonomousJobQueueDeps
|
|
164
|
+
}
|
|
124
165
|
|
|
125
|
-
|
|
126
|
-
|
|
166
|
+
export function startAutonomousJobWorker(options: AutonomousJobWorkerOptions): WorkerHandle {
|
|
167
|
+
_deps = options.deps
|
|
168
|
+
const handle = autonomousJobQueue.startWorker({
|
|
169
|
+
registerSignals: options.registerSignals,
|
|
170
|
+
connectionProvider: options.connectionProvider,
|
|
127
171
|
})
|
|
128
172
|
|
|
173
|
+
void Effect.runPromise(
|
|
174
|
+
Effect.catch(options.deps.autonomousJobService.recoverActiveJobs(), (error) =>
|
|
175
|
+
Effect.sync(() => {
|
|
176
|
+
serverLogger.error`Autonomous job startup recovery failed: ${error}`
|
|
177
|
+
}),
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
|
|
129
181
|
return handle
|
|
130
182
|
}
|
|
131
183
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
184
|
+
runStandaloneQueueWorker((runtime) => {
|
|
185
|
+
const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))
|
|
186
|
+
startAutonomousJobWorker({
|
|
187
|
+
connectionProvider: () => resolve(RedisServiceTag).getConnectionForBullMQ(),
|
|
188
|
+
deps: { databaseService: resolve(DatabaseServiceTag), autonomousJobService: resolve(AutonomousJobServiceTag) },
|
|
189
|
+
})
|
|
190
|
+
})
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { Job } from 'bullmq'
|
|
2
|
+
import { Effect } from 'effect'
|
|
3
|
+
import type { Context } from 'effect'
|
|
4
|
+
import type IORedis from 'ioredis'
|
|
2
5
|
|
|
3
6
|
import { ensureRecordId } from '../db/record-id'
|
|
4
|
-
import { databaseService } from '../db/service'
|
|
5
7
|
import { TABLES } from '../db/tables'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
+
import { ConfigurationError } from '../effect/errors'
|
|
9
|
+
import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
|
|
10
|
+
import { ContextCompactionServiceTag } from '../services/context-compaction.service'
|
|
11
|
+
import { ThreadServiceTag } from '../services/thread/thread.service'
|
|
8
12
|
import { createQueueFactory } from './queue-factory'
|
|
13
|
+
import { runStandaloneQueueWorker } from './standalone-worker'
|
|
9
14
|
|
|
10
15
|
interface ContextCompactionJob {
|
|
11
16
|
domain: 'thread'
|
|
@@ -13,17 +18,38 @@ interface ContextCompactionJob {
|
|
|
13
18
|
contextSize?: number
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
interface ContextCompactionQueueDeps {
|
|
22
|
+
databaseService: Context.Service.Shape<typeof DatabaseServiceTag>
|
|
23
|
+
threadService: Context.Service.Shape<typeof ThreadServiceTag>
|
|
24
|
+
contextCompactionService: Context.Service.Shape<typeof ContextCompactionServiceTag>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let _deps: ContextCompactionQueueDeps | null = null
|
|
28
|
+
function getDeps(): ContextCompactionQueueDeps {
|
|
29
|
+
if (!_deps)
|
|
30
|
+
throw new ConfigurationError({
|
|
31
|
+
message: 'Context compaction queue is not configured. Initialize the runtime before starting the worker.',
|
|
32
|
+
key: 'queue-deps',
|
|
33
|
+
})
|
|
34
|
+
return _deps
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function processContextCompactionJob(job: Job<ContextCompactionJob>): Promise<void> {
|
|
38
|
+
const { threadService, contextCompactionService } = getDeps()
|
|
18
39
|
|
|
19
40
|
const { entityId, contextSize } = job.data
|
|
20
41
|
const threadRef = ensureRecordId(entityId, TABLES.THREAD)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
return Effect.runPromise(
|
|
43
|
+
Effect.ensuring(
|
|
44
|
+
Effect.asVoid(
|
|
45
|
+
Effect.gen(function* () {
|
|
46
|
+
yield* threadService.setCompacting(threadRef, true)
|
|
47
|
+
yield* contextCompactionService.compactThreadHistory({ threadId: threadRef, contextSize })
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
Effect.ignore(threadService.setCompacting(threadRef, false)),
|
|
51
|
+
),
|
|
52
|
+
)
|
|
27
53
|
}
|
|
28
54
|
|
|
29
55
|
const contextCompaction = createQueueFactory<ContextCompactionJob>({
|
|
@@ -33,6 +59,7 @@ const contextCompaction = createQueueFactory<ContextCompactionJob>({
|
|
|
33
59
|
concurrency: 2,
|
|
34
60
|
lockDuration: 300_000,
|
|
35
61
|
defaultJobOptions: { attempts: 2, backoff: { type: 'exponential', delay: 3_000 } },
|
|
62
|
+
prepare: () => getDeps().databaseService.connect(),
|
|
36
63
|
processor: processContextCompactionJob,
|
|
37
64
|
})
|
|
38
65
|
|
|
@@ -40,8 +67,26 @@ export function enqueueContextCompaction(job: ContextCompactionJob) {
|
|
|
40
67
|
return contextCompaction.enqueue(job, { deduplication: { id: `compact:${job.domain}:${job.entityId}` } })
|
|
41
68
|
}
|
|
42
69
|
|
|
43
|
-
export
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
70
|
+
export function startContextCompactionWorker(options: {
|
|
71
|
+
registerSignals?: boolean
|
|
72
|
+
connectionProvider: () => IORedis
|
|
73
|
+
deps: ContextCompactionQueueDeps
|
|
74
|
+
}): ReturnType<typeof contextCompaction.startWorker> {
|
|
75
|
+
_deps = options.deps
|
|
76
|
+
return contextCompaction.startWorker({
|
|
77
|
+
registerSignals: options.registerSignals,
|
|
78
|
+
connectionProvider: options.connectionProvider,
|
|
79
|
+
})
|
|
47
80
|
}
|
|
81
|
+
|
|
82
|
+
runStandaloneQueueWorker((runtime) => {
|
|
83
|
+
const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))
|
|
84
|
+
startContextCompactionWorker({
|
|
85
|
+
connectionProvider: () => resolve(RedisServiceTag).getConnectionForBullMQ(),
|
|
86
|
+
deps: {
|
|
87
|
+
databaseService: resolve(DatabaseServiceTag),
|
|
88
|
+
threadService: resolve(ThreadServiceTag),
|
|
89
|
+
contextCompactionService: resolve(ContextCompactionServiceTag),
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
})
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { Job } from 'bullmq'
|
|
2
|
+
import { Effect } from 'effect'
|
|
3
|
+
import type { Context } from 'effect'
|
|
4
|
+
import type IORedis from 'ioredis'
|
|
2
5
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
6
|
+
import { ConfigurationError } from '../effect/errors'
|
|
7
|
+
import { DatabaseServiceTag, RedisServiceTag } from '../effect/services'
|
|
8
|
+
import { PlanExecutorServiceTag } from '../services/plan/plan-executor.service'
|
|
5
9
|
import { createQueueFactory } from './queue-factory'
|
|
10
|
+
import { runStandaloneQueueWorker } from './standalone-worker'
|
|
6
11
|
|
|
7
12
|
export interface DelayedNodePromotionJob {
|
|
8
13
|
runId: string
|
|
@@ -12,13 +17,30 @@ export interface DelayedNodePromotionJob {
|
|
|
12
17
|
|
|
13
18
|
export const DELAYED_NODE_PROMOTION_QUEUE = 'delayed-node-promotion'
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
interface DelayedNodePromotionQueueDeps {
|
|
21
|
+
databaseService: Context.Service.Shape<typeof DatabaseServiceTag>
|
|
22
|
+
planExecutorService: Context.Service.Shape<typeof PlanExecutorServiceTag>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let _deps: DelayedNodePromotionQueueDeps | null = null
|
|
26
|
+
function getDeps(): DelayedNodePromotionQueueDeps {
|
|
27
|
+
if (!_deps)
|
|
28
|
+
throw new ConfigurationError({
|
|
29
|
+
message: 'Delayed node promotion queue is not configured. Initialize the runtime before starting the worker.',
|
|
30
|
+
key: 'queue-deps',
|
|
31
|
+
})
|
|
32
|
+
return _deps
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function processDelayedNodePromotionJob(job: Job<DelayedNodePromotionJob>): Promise<void> {
|
|
36
|
+
const { planExecutorService } = getDeps()
|
|
37
|
+
return Promise.resolve(
|
|
38
|
+
planExecutorService.promoteDelayedNode({
|
|
39
|
+
runId: job.data.runId,
|
|
40
|
+
nodeId: job.data.nodeId,
|
|
41
|
+
emittedBy: job.data.emittedBy,
|
|
42
|
+
}),
|
|
43
|
+
).then(() => undefined)
|
|
22
44
|
}
|
|
23
45
|
|
|
24
46
|
const delayedNodePromotion = createQueueFactory<DelayedNodePromotionJob>({
|
|
@@ -27,15 +49,30 @@ const delayedNodePromotion = createQueueFactory<DelayedNodePromotionJob>({
|
|
|
27
49
|
jobName: 'promote-node',
|
|
28
50
|
concurrency: 1,
|
|
29
51
|
defaultJobOptions: { attempts: 3, backoff: { type: 'exponential', delay: 5000 } },
|
|
52
|
+
prepare: () => getDeps().databaseService.connect(),
|
|
30
53
|
processor: processDelayedNodePromotionJob,
|
|
31
54
|
})
|
|
32
55
|
|
|
33
|
-
export
|
|
34
|
-
|
|
56
|
+
export function enqueueDelayedNodePromotion(job: DelayedNodePromotionJob, delayMs: number) {
|
|
57
|
+
return delayedNodePromotion.enqueue(job, { delay: delayMs, jobId: `promote:${job.runId}:${job.nodeId}` })
|
|
35
58
|
}
|
|
36
59
|
|
|
37
|
-
export
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
60
|
+
export function startDelayedNodePromotionWorker(options: {
|
|
61
|
+
registerSignals?: boolean
|
|
62
|
+
connectionProvider: () => IORedis
|
|
63
|
+
deps: DelayedNodePromotionQueueDeps
|
|
64
|
+
}): ReturnType<typeof delayedNodePromotion.startWorker> {
|
|
65
|
+
_deps = options.deps
|
|
66
|
+
return delayedNodePromotion.startWorker({
|
|
67
|
+
registerSignals: options.registerSignals,
|
|
68
|
+
connectionProvider: options.connectionProvider,
|
|
69
|
+
})
|
|
41
70
|
}
|
|
71
|
+
|
|
72
|
+
runStandaloneQueueWorker((runtime) => {
|
|
73
|
+
const resolve = <I, T>(tag: Context.Key<I, T>): T => runtime.runSync(Effect.service(tag))
|
|
74
|
+
startDelayedNodePromotionWorker({
|
|
75
|
+
connectionProvider: () => resolve(RedisServiceTag).getConnectionForBullMQ(),
|
|
76
|
+
deps: { databaseService: resolve(DatabaseServiceTag), planExecutorService: resolve(PlanExecutorServiceTag) },
|
|
77
|
+
})
|
|
78
|
+
})
|