@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
|
@@ -1,28 +1,10 @@
|
|
|
1
|
+
import { Context, Schema, Effect, Fiber, Layer, PubSub, Stream } from 'effect'
|
|
1
2
|
import type { Redis } from 'ioredis'
|
|
2
3
|
import type { Publisher, Subscriber } from 'resumable-stream/ioredis'
|
|
3
4
|
import { createResumableStreamContext } from 'resumable-stream/ioredis'
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
function toSubscriber(client: Redis): Subscriber {
|
|
8
|
-
const handlers = new Map<string, (message: string) => void>()
|
|
9
|
-
const messageListener = (channel: string, message: string) => {
|
|
10
|
-
handlers.get(channel)?.(message)
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
connect: () => Promise.resolve(),
|
|
14
|
-
subscribe: async (channel, callback) => {
|
|
15
|
-
if (handlers.size === 0) client.on('message', messageListener)
|
|
16
|
-
handlers.set(channel, callback)
|
|
17
|
-
await client.subscribe(channel)
|
|
18
|
-
},
|
|
19
|
-
unsubscribe: async (channel) => {
|
|
20
|
-
handlers.delete(channel)
|
|
21
|
-
if (handlers.size === 0) client.removeListener('message', messageListener)
|
|
22
|
-
return client.unsubscribe(channel)
|
|
23
|
-
},
|
|
24
|
-
}
|
|
25
|
-
}
|
|
6
|
+
import { RedisServiceTag } from '../effect/services'
|
|
7
|
+
import type { RedisConnectionManager } from './connection'
|
|
26
8
|
|
|
27
9
|
function toPublisher(client: Redis): Publisher {
|
|
28
10
|
return {
|
|
@@ -34,35 +16,91 @@ function toPublisher(client: Redis): Publisher {
|
|
|
34
16
|
}
|
|
35
17
|
}
|
|
36
18
|
|
|
37
|
-
|
|
19
|
+
type SharedSubscriberEvent = { readonly channel: string; readonly message: string }
|
|
20
|
+
|
|
21
|
+
class SharedSubscriberCloseError extends Schema.TaggedErrorClass<SharedSubscriberCloseError>()(
|
|
22
|
+
'SharedSubscriberCloseError',
|
|
23
|
+
{ message: Schema.String, cause: Schema.optional(Schema.Defect) },
|
|
24
|
+
) {}
|
|
38
25
|
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
export class SharedThreadStreamSubscriberTag extends Context.Service<
|
|
27
|
+
SharedThreadStreamSubscriberTag,
|
|
28
|
+
{ readonly subscriber: Subscriber }
|
|
29
|
+
>()('SharedThreadStreamSubscriber') {}
|
|
30
|
+
|
|
31
|
+
export const SharedThreadStreamSubscriberLive = Layer.effect(
|
|
32
|
+
SharedThreadStreamSubscriberTag,
|
|
33
|
+
Effect.gen(function* () {
|
|
34
|
+
const redisManager = yield* RedisServiceTag
|
|
41
35
|
// Disable enableReadyCheck — the ready check sends INFO which is rejected
|
|
42
36
|
// on connections in subscribe mode, causing unhandled ioredis error events.
|
|
43
|
-
const client =
|
|
37
|
+
const client = redisManager.getConnection().duplicate({ enableReadyCheck: false })
|
|
44
38
|
client.on('error', () => {}) // prevent [ioredis] Unhandled error event logs
|
|
45
|
-
sharedSubscriber = { client, subscriber: toSubscriber(client) }
|
|
46
|
-
}
|
|
47
|
-
return sharedSubscriber.subscriber
|
|
48
|
-
}
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
40
|
+
const events = yield* PubSub.unbounded<SharedSubscriberEvent>()
|
|
41
|
+
const handlers = new Map<string, (message: string) => void>()
|
|
42
|
+
|
|
43
|
+
const dispatchFiber = yield* Effect.forkScoped(
|
|
44
|
+
Stream.fromPubSub(events).pipe(
|
|
45
|
+
Stream.runForEach((event) =>
|
|
46
|
+
Effect.sync(() => {
|
|
47
|
+
handlers.get(event.channel)?.(event.message)
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
const currentContext = yield* Effect.context()
|
|
54
|
+
const runFork = Effect.runForkWith(currentContext)
|
|
55
|
+
const messageListener = (channel: string, message: string) => {
|
|
56
|
+
void runFork(PubSub.publish(events, { channel, message }).pipe(Effect.asVoid))
|
|
57
|
+
}
|
|
58
|
+
client.on('message', messageListener)
|
|
59
|
+
|
|
60
|
+
const subscribe = (channel: string, callback: (message: string) => void): Promise<void> => {
|
|
61
|
+
handlers.set(channel, callback)
|
|
62
|
+
return client.subscribe(channel).then(() => undefined)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const unsubscribe = (channel: string): Promise<void> => {
|
|
66
|
+
handlers.delete(channel)
|
|
67
|
+
return client.unsubscribe(channel).then(() => undefined)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const subscriber: Subscriber = {
|
|
71
|
+
connect: () => Promise.resolve(),
|
|
72
|
+
subscribe: (channel, callback) => subscribe(channel, callback),
|
|
73
|
+
unsubscribe: (channel) => unsubscribe(channel),
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
yield* Effect.addFinalizer(() =>
|
|
77
|
+
Effect.gen(function* () {
|
|
78
|
+
handlers.clear()
|
|
79
|
+
client.removeListener('message', messageListener)
|
|
80
|
+
yield* Fiber.interrupt(dispatchFiber)
|
|
81
|
+
yield* PubSub.shutdown(events)
|
|
82
|
+
yield* Effect.tryPromise({
|
|
83
|
+
try: () => client.quit(),
|
|
84
|
+
catch: (cause) =>
|
|
85
|
+
new SharedSubscriberCloseError({ message: 'Failed to quit shared stream subscriber.', cause }),
|
|
86
|
+
}).pipe(
|
|
87
|
+
Effect.catch(() =>
|
|
88
|
+
Effect.sync(() => {
|
|
89
|
+
client.disconnect()
|
|
90
|
+
}),
|
|
91
|
+
),
|
|
92
|
+
)
|
|
93
|
+
}),
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
return { subscriber }
|
|
97
|
+
}),
|
|
98
|
+
)
|
|
60
99
|
|
|
61
|
-
export function createThreadResumableContext(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
})
|
|
100
|
+
export function createThreadResumableContext(
|
|
101
|
+
redisManager: Pick<RedisConnectionManager, 'getConnection'>,
|
|
102
|
+
subscriber: Subscriber,
|
|
103
|
+
) {
|
|
104
|
+
const redis = redisManager.getConnection()
|
|
105
|
+
return createResumableStreamContext({ waitUntil: null, subscriber, publisher: toPublisher(redis) })
|
|
68
106
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAgentDisplayNames } from '../config/agent-defaults'
|
|
2
2
|
import { asRecord, readOptionalString } from './thread-chat-helpers'
|
|
3
3
|
|
|
4
4
|
interface RuntimeAgentIdentityOverrides {
|
|
@@ -58,5 +58,5 @@ export function resolveRuntimeAgentDisplayName(overrides: RuntimeAgentIdentityOv
|
|
|
58
58
|
return override
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
return
|
|
61
|
+
return getAgentDisplayNames()[agentId] ?? agentId
|
|
62
62
|
}
|
|
@@ -162,10 +162,13 @@ export function buildThreadAgentToolPolicy<TAgent extends string, TSkill extends
|
|
|
162
162
|
linearInstalled: boolean
|
|
163
163
|
githubInstalled: boolean
|
|
164
164
|
provideRepoTool: boolean
|
|
165
|
+
leadAgentId?: TAgent
|
|
166
|
+
onboardingOwnerAgentId?: TAgent
|
|
165
167
|
getAgentSkills: (agentId: TAgent, mode: ChatMode) => TSkill[]
|
|
166
168
|
}): AgentToolPolicy<TSkill> {
|
|
167
169
|
const resolvedMode = params.mode ?? toChatMode(params.threadType)
|
|
168
|
-
const
|
|
170
|
+
const leadAgentId = params.leadAgentId ?? (getLeadAgentId() as TAgent)
|
|
171
|
+
const onboardingOwnerAgentId = params.onboardingOwnerAgentId ?? (resolveOnboardingOwnerAgentId(leadAgentId) as TAgent)
|
|
169
172
|
const skills = resolveActiveAgentSkills({
|
|
170
173
|
agentId: params.agentId,
|
|
171
174
|
threadType: params.threadType,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
2
2
|
import type { LanguageModelUsage, UIMessageStreamOptions } from 'ai'
|
|
3
|
+
import { Duration, Effect, Fiber } from 'effect'
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
+
import { getAgentDisplayNames, getLeadAgentDisplayName } from '../config/agent-defaults'
|
|
6
|
+
import { nowEpochMillis } from '../utils/date-time'
|
|
5
7
|
import { readRecord as _readRecord } from '../utils/string'
|
|
6
8
|
|
|
7
9
|
export function readFiniteNumber(value: unknown): number | undefined {
|
|
@@ -32,7 +34,7 @@ export function createAgentMessageMetadata(params: {
|
|
|
32
34
|
}): NonNullable<UIMessageStreamOptions<ChatMessage>['messageMetadata']> {
|
|
33
35
|
return ({ part }) => {
|
|
34
36
|
if (part.type === 'start') {
|
|
35
|
-
return { agentId: params.agentId, agentName: params.agentName, createdAt:
|
|
37
|
+
return { agentId: params.agentId, agentName: params.agentName, createdAt: nowEpochMillis() }
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
if (part.type === 'finish') {
|
|
@@ -100,13 +102,21 @@ export function createServerRunAbortController(externalAbortSignal?: AbortSignal
|
|
|
100
102
|
export function createTimedAbortSignal(parentSignal: AbortSignal, timeoutMs: number) {
|
|
101
103
|
const controller = new AbortController()
|
|
102
104
|
let didTimeout = false
|
|
105
|
+
let disposed = false
|
|
103
106
|
const abortFromParent = () => {
|
|
104
107
|
controller.abort((parentSignal as AbortSignal & { reason?: unknown }).reason)
|
|
105
108
|
}
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
const timeoutFiber = Effect.runFork(
|
|
110
|
+
Effect.sleep(Duration.millis(timeoutMs)).pipe(
|
|
111
|
+
Effect.tap(() =>
|
|
112
|
+
Effect.sync(() => {
|
|
113
|
+
if (disposed || controller.signal.aborted) return
|
|
114
|
+
didTimeout = true
|
|
115
|
+
controller.abort(new Error(`Timed out after ${timeoutMs}ms`))
|
|
116
|
+
}),
|
|
117
|
+
),
|
|
118
|
+
),
|
|
119
|
+
)
|
|
110
120
|
|
|
111
121
|
if (parentSignal.aborted) {
|
|
112
122
|
abortFromParent()
|
|
@@ -118,14 +128,15 @@ export function createTimedAbortSignal(parentSignal: AbortSignal, timeoutMs: num
|
|
|
118
128
|
signal: controller.signal,
|
|
119
129
|
didTimeout: () => didTimeout,
|
|
120
130
|
dispose: () => {
|
|
121
|
-
|
|
131
|
+
disposed = true
|
|
122
132
|
parentSignal.removeEventListener('abort', abortFromParent)
|
|
133
|
+
void Effect.runFork(Fiber.interrupt(timeoutFiber))
|
|
123
134
|
},
|
|
124
135
|
}
|
|
125
136
|
}
|
|
126
137
|
|
|
127
138
|
export function buildSpecialistTaskMessage(params: { agentId: string; task: string }): ChatMessage {
|
|
128
|
-
const displayName =
|
|
139
|
+
const displayName = getAgentDisplayNames()[params.agentId] ?? params.agentId
|
|
129
140
|
const leadAgentDisplayName = getLeadAgentDisplayName()
|
|
130
141
|
return {
|
|
131
142
|
id: Bun.randomUUIDv7(),
|
|
@@ -133,6 +144,6 @@ export function buildSpecialistTaskMessage(params: { agentId: string; task: stri
|
|
|
133
144
|
parts: [
|
|
134
145
|
{ type: 'text', text: [`${leadAgentDisplayName} request for ${displayName}:`, params.task.trim()].join('\n') },
|
|
135
146
|
],
|
|
136
|
-
metadata: { createdAt:
|
|
147
|
+
metadata: { createdAt: nowEpochMillis() },
|
|
137
148
|
}
|
|
138
149
|
}
|
|
@@ -1,25 +1,108 @@
|
|
|
1
|
-
|
|
1
|
+
import { Cause, Context, Schema, Duration, Effect, Latch, Layer } from 'effect'
|
|
2
|
+
|
|
3
|
+
import { effectTryPromise } from '../effect/helpers'
|
|
4
|
+
import { nowEpochMillis } from '../utils/date-time'
|
|
5
|
+
|
|
6
|
+
const COMPACTION_WAIT_REFRESH_MS = 1_000
|
|
2
7
|
const COMPACTION_MAX_WAIT_MS = 120_000
|
|
3
8
|
|
|
4
|
-
|
|
9
|
+
class WaitForCompactionError extends Schema.TaggedErrorClass<WaitForCompactionError>()('WaitForCompactionError', {
|
|
10
|
+
entityId: Schema.String,
|
|
11
|
+
entityLabel: Schema.String,
|
|
12
|
+
message: Schema.String,
|
|
13
|
+
cause: Schema.optional(Schema.Defect),
|
|
14
|
+
}) {}
|
|
15
|
+
|
|
16
|
+
function toWaitForCompactionError(params: {
|
|
5
17
|
entityId: string
|
|
6
18
|
entityLabel: string
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
throw new Error(
|
|
17
|
-
`${params.entityLabel} ${params.entityId} compaction did not complete within ${COMPACTION_MAX_WAIT_MS}ms`,
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
await Bun.sleep(COMPACTION_POLL_INTERVAL_MS)
|
|
21
|
-
entity = await params.loadEntity()
|
|
22
|
-
}
|
|
19
|
+
cause: unknown
|
|
20
|
+
}): WaitForCompactionError {
|
|
21
|
+
return new WaitForCompactionError({
|
|
22
|
+
entityId: params.entityId,
|
|
23
|
+
entityLabel: params.entityLabel,
|
|
24
|
+
message: params.cause instanceof Error ? params.cause.message : String(params.cause),
|
|
25
|
+
cause: params.cause,
|
|
26
|
+
})
|
|
27
|
+
}
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
interface CompactionCoordination {
|
|
30
|
+
readonly signal: (entityId: string, compacting: boolean) => Effect.Effect<void>
|
|
31
|
+
readonly waitIfNeeded: <TEntity>(params: {
|
|
32
|
+
entityId: string
|
|
33
|
+
entityLabel: string
|
|
34
|
+
loadEntity: () => PromiseLike<TEntity> | Effect.Effect<TEntity, unknown>
|
|
35
|
+
isCompacting: (entity: TEntity) => boolean
|
|
36
|
+
}) => Effect.Effect<TEntity, WaitForCompactionError>
|
|
25
37
|
}
|
|
38
|
+
|
|
39
|
+
export class CompactionCoordinationTag extends Context.Service<CompactionCoordinationTag, CompactionCoordination>()(
|
|
40
|
+
'CompactionCoordination',
|
|
41
|
+
) {}
|
|
42
|
+
|
|
43
|
+
export const CompactionCoordinationLive = Layer.effect(
|
|
44
|
+
CompactionCoordinationTag,
|
|
45
|
+
Effect.sync((): CompactionCoordination => {
|
|
46
|
+
const latches = new Map<string, Latch.Latch>()
|
|
47
|
+
|
|
48
|
+
function getLatch(entityId: string): Latch.Latch {
|
|
49
|
+
let latch = latches.get(entityId)
|
|
50
|
+
if (!latch) {
|
|
51
|
+
latch = Latch.makeUnsafe(true)
|
|
52
|
+
latches.set(entityId, latch)
|
|
53
|
+
}
|
|
54
|
+
return latch
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
signal: (entityId, compacting) =>
|
|
59
|
+
Effect.sync(() => {
|
|
60
|
+
const latch = getLatch(entityId)
|
|
61
|
+
if (compacting) {
|
|
62
|
+
Latch.closeUnsafe(latch)
|
|
63
|
+
} else {
|
|
64
|
+
Latch.openUnsafe(latch)
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
|
|
68
|
+
waitIfNeeded: Effect.fn('CompactionCoordination.waitIfNeeded')(function* <TEntity>(params: {
|
|
69
|
+
entityId: string
|
|
70
|
+
entityLabel: string
|
|
71
|
+
loadEntity: () => PromiseLike<TEntity> | Effect.Effect<TEntity, unknown>
|
|
72
|
+
isCompacting: (entity: TEntity) => boolean
|
|
73
|
+
}) {
|
|
74
|
+
const deadline = nowEpochMillis() + COMPACTION_MAX_WAIT_MS
|
|
75
|
+
const latch = getLatch(params.entityId)
|
|
76
|
+
let entity = yield* effectTryPromise(
|
|
77
|
+
() => params.loadEntity(),
|
|
78
|
+
(cause) => toWaitForCompactionError({ entityId: params.entityId, entityLabel: params.entityLabel, cause }),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
while (params.isCompacting(entity)) {
|
|
82
|
+
Latch.closeUnsafe(latch)
|
|
83
|
+
if (nowEpochMillis() > deadline) {
|
|
84
|
+
return yield* new WaitForCompactionError({
|
|
85
|
+
entityId: params.entityId,
|
|
86
|
+
entityLabel: params.entityLabel,
|
|
87
|
+
message: `${params.entityLabel} ${params.entityId} compaction did not complete within ${COMPACTION_MAX_WAIT_MS}ms`,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const remainingMs = Math.max(0, deadline - nowEpochMillis())
|
|
92
|
+
const refreshWindowMs = Math.min(COMPACTION_WAIT_REFRESH_MS, remainingMs)
|
|
93
|
+
yield* latch.await.pipe(
|
|
94
|
+
Effect.timeout(Duration.millis(refreshWindowMs)),
|
|
95
|
+
Effect.catchIf(Cause.isTimeoutError, () => Effect.void),
|
|
96
|
+
)
|
|
97
|
+
entity = yield* effectTryPromise(
|
|
98
|
+
() => params.loadEntity(),
|
|
99
|
+
(cause) => toWaitForCompactionError({ entityId: params.entityId, entityLabel: params.entityLabel, cause }),
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
Latch.openUnsafe(latch)
|
|
104
|
+
return entity
|
|
105
|
+
}),
|
|
106
|
+
}
|
|
107
|
+
}),
|
|
108
|
+
)
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { Effect, Fiber, FiberMap } from 'effect'
|
|
2
|
+
|
|
1
3
|
export class ChatRunRegistry {
|
|
2
|
-
private controllers = new Map<string, AbortController>()
|
|
4
|
+
private readonly controllers = new Map<string, AbortController>()
|
|
5
|
+
|
|
6
|
+
constructor(private readonly trackedRuns: FiberMap.FiberMap<string>) {}
|
|
3
7
|
|
|
4
8
|
has(runId: string): boolean {
|
|
5
9
|
return this.controllers.has(runId)
|
|
@@ -16,9 +20,39 @@ export class ChatRunRegistry {
|
|
|
16
20
|
stop(runId: string, reason?: unknown): boolean {
|
|
17
21
|
const controller = this.controllers.get(runId)
|
|
18
22
|
if (!controller) return false
|
|
19
|
-
|
|
20
23
|
this.controllers.delete(runId)
|
|
21
24
|
controller.abort(reason)
|
|
25
|
+
void Effect.runFork(FiberMap.remove(this.trackedRuns, runId))
|
|
22
26
|
return true
|
|
23
27
|
}
|
|
28
|
+
|
|
29
|
+
trackRunEffect<A, E, R>(
|
|
30
|
+
runId: string,
|
|
31
|
+
controller: AbortController,
|
|
32
|
+
effect: Effect.Effect<A, E, R>,
|
|
33
|
+
): Effect.Effect<A, E, R> {
|
|
34
|
+
return Effect.gen(
|
|
35
|
+
function* (this: ChatRunRegistry) {
|
|
36
|
+
this.controllers.set(runId, controller)
|
|
37
|
+
const fiber = yield* FiberMap.run(
|
|
38
|
+
this.trackedRuns,
|
|
39
|
+
runId,
|
|
40
|
+
effect.pipe(
|
|
41
|
+
Effect.ensuring(
|
|
42
|
+
Effect.sync(() => {
|
|
43
|
+
if (this.controllers.get(runId) === controller) {
|
|
44
|
+
this.controllers.delete(runId)
|
|
45
|
+
}
|
|
46
|
+
}),
|
|
47
|
+
),
|
|
48
|
+
),
|
|
49
|
+
)
|
|
50
|
+
return yield* Fiber.join(fiber)
|
|
51
|
+
}.bind(this),
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
stopEffect(runId: string, reason?: unknown): Effect.Effect<boolean> {
|
|
56
|
+
return Effect.sync(() => this.stop(runId, reason))
|
|
57
|
+
}
|
|
24
58
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Schema, Effect } from 'effect'
|
|
2
|
+
|
|
3
|
+
import { createContextCompactionAgent } from '../../system-agents/context-compaction.agent'
|
|
4
|
+
import type { GenerateHelperStructuredParams, GenerateHelperTextParams } from '../helper-model'
|
|
5
|
+
import {
|
|
6
|
+
buildContextCompactionPrompt,
|
|
7
|
+
buildMemoryBlockCompactionPrompt,
|
|
8
|
+
ContextCompactionOutputSchema,
|
|
9
|
+
createContextCompactionRuntime,
|
|
10
|
+
parseCompactionOutput,
|
|
11
|
+
} from './context-compaction'
|
|
12
|
+
import type { ContextCompactionRunnerParams } from './context-compaction'
|
|
13
|
+
import {
|
|
14
|
+
COMPACTION_CHUNK_MAX_CHARS,
|
|
15
|
+
CONTEXT_COMPACTION_INCLUDED_TOOL_NAMES,
|
|
16
|
+
CONTEXT_COMPACTION_INCLUDED_TOOL_PREFIXES,
|
|
17
|
+
CONTEXT_COMPACTION_THRESHOLD_RATIO,
|
|
18
|
+
CONTEXT_OUTPUT_RESERVE_TOKENS,
|
|
19
|
+
CONTEXT_SAFETY_MARGIN_TOKENS,
|
|
20
|
+
SUMMARY_ROLLUP_MAX_TOKENS,
|
|
21
|
+
} from './context-compaction-constants'
|
|
22
|
+
|
|
23
|
+
const CONTEXT_COMPACTION_MAX_OUTPUT_TOKENS = 512
|
|
24
|
+
|
|
25
|
+
interface HelperModelRuntime {
|
|
26
|
+
generateHelperStructured<T>(params: GenerateHelperStructuredParams<T>): Promise<T>
|
|
27
|
+
generateHelperText(params: GenerateHelperTextParams): Promise<string>
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface CreateContextCompactionRuntimeDeps {
|
|
31
|
+
helperModelRuntime: HelperModelRuntime
|
|
32
|
+
now?: () => number
|
|
33
|
+
randomId?: () => string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class ContextCompactionRuntimeError extends Schema.TaggedErrorClass<ContextCompactionRuntimeError>()(
|
|
37
|
+
'ContextCompactionRuntimeError',
|
|
38
|
+
{ message: Schema.String, cause: Schema.Defect },
|
|
39
|
+
) {}
|
|
40
|
+
|
|
41
|
+
function tryContextCompactionPromise<A>(
|
|
42
|
+
message: string,
|
|
43
|
+
thunk: () => PromiseLike<A>,
|
|
44
|
+
): Effect.Effect<A, ContextCompactionRuntimeError> {
|
|
45
|
+
return Effect.tryPromise({
|
|
46
|
+
try: () => Promise.resolve(thunk()),
|
|
47
|
+
catch: (cause) => new ContextCompactionRuntimeError({ message, cause }),
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function runContextCompacter(helperModelRuntime: HelperModelRuntime, params: ContextCompactionRunnerParams) {
|
|
52
|
+
return Effect.runPromise(
|
|
53
|
+
tryContextCompactionPromise('Failed to compact runtime context.', () =>
|
|
54
|
+
helperModelRuntime.generateHelperStructured({
|
|
55
|
+
tag: 'context-compaction',
|
|
56
|
+
createAgent: createContextCompactionAgent,
|
|
57
|
+
messages: [
|
|
58
|
+
{
|
|
59
|
+
role: 'user',
|
|
60
|
+
content: buildContextCompactionPrompt({
|
|
61
|
+
previousSummary: params.previousSummary,
|
|
62
|
+
transcript: params.transcript,
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
schema: ContextCompactionOutputSchema,
|
|
67
|
+
maxOutputTokens: 8_000,
|
|
68
|
+
}),
|
|
69
|
+
).pipe(Effect.map(parseCompactionOutput)),
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function createWiredContextCompactionRuntime(deps: CreateContextCompactionRuntimeDeps) {
|
|
74
|
+
const { helperModelRuntime } = deps
|
|
75
|
+
|
|
76
|
+
const runtime = createContextCompactionRuntime({
|
|
77
|
+
runCompacter: (params) => runContextCompacter(helperModelRuntime, params),
|
|
78
|
+
now: deps.now,
|
|
79
|
+
randomId: deps.randomId,
|
|
80
|
+
thresholdRatio: CONTEXT_COMPACTION_THRESHOLD_RATIO,
|
|
81
|
+
outputReserveTokens: CONTEXT_OUTPUT_RESERVE_TOKENS,
|
|
82
|
+
safetyMarginTokens: CONTEXT_SAFETY_MARGIN_TOKENS,
|
|
83
|
+
compactionChunkMaxChars: COMPACTION_CHUNK_MAX_CHARS,
|
|
84
|
+
summaryRollupMaxTokens: SUMMARY_ROLLUP_MAX_TOKENS,
|
|
85
|
+
includedToolNames: CONTEXT_COMPACTION_INCLUDED_TOOL_NAMES,
|
|
86
|
+
includedToolPrefixes: CONTEXT_COMPACTION_INCLUDED_TOOL_PREFIXES,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
function compactMemoryBlockSummary(params: { previousSummary: string; newEntriesText: string }): Promise<string> {
|
|
90
|
+
const previousSummary = params.previousSummary.trim()
|
|
91
|
+
const newEntriesText = params.newEntriesText.trim()
|
|
92
|
+
if (!previousSummary && !newEntriesText) return Promise.resolve('')
|
|
93
|
+
|
|
94
|
+
return Effect.runPromise(
|
|
95
|
+
tryContextCompactionPromise('Failed to compact memory block summary.', () =>
|
|
96
|
+
helperModelRuntime.generateHelperText({
|
|
97
|
+
tag: 'memory-block-compaction',
|
|
98
|
+
createAgent: createContextCompactionAgent,
|
|
99
|
+
messages: [{ role: 'user', content: buildMemoryBlockCompactionPrompt({ previousSummary, newEntriesText }) }],
|
|
100
|
+
maxOutputTokens: CONTEXT_COMPACTION_MAX_OUTPUT_TOKENS,
|
|
101
|
+
}),
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return { ...runtime, compactMemoryBlockSummary }
|
|
107
|
+
}
|