@lota-sdk/core 0.4.9 → 0.4.11
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 +2 -2
- package/src/ai/embedding-cache.ts +3 -1
- package/src/ai-gateway/ai-gateway.ts +164 -82
- package/src/ai-gateway/index.ts +16 -1
- package/src/config/agent-defaults.ts +4 -107
- package/src/config/agent-types.ts +1 -1
- package/src/config/background-processing.ts +1 -1
- package/src/config/index.ts +0 -1
- package/src/config/logger.ts +22 -25
- package/src/config/thread-defaults.ts +1 -10
- package/src/create-runtime.ts +145 -670
- package/src/db/base.service.ts +30 -38
- package/src/db/memory-query-builder.ts +2 -1
- package/src/db/memory-store.ts +29 -20
- package/src/db/memory.ts +188 -195
- package/src/db/service-normalization.ts +97 -64
- package/src/db/service.ts +496 -384
- package/src/db/startup.ts +30 -19
- package/src/effect/helpers.ts +30 -5
- package/src/effect/index.ts +7 -7
- package/src/effect/layers.ts +75 -72
- package/src/effect/services.ts +15 -11
- package/src/embeddings/provider.ts +65 -71
- package/src/index.ts +13 -12
- package/src/queues/autonomous-job.queue.ts +177 -143
- package/src/queues/context-compaction.queue.ts +41 -39
- package/src/queues/delayed-node-promotion.queue.ts +61 -42
- package/src/queues/document-processor.queue.ts +5 -3
- package/src/queues/index.ts +1 -0
- package/src/queues/memory-consolidation.queue.ts +79 -53
- package/src/queues/organization-learning.queue.ts +70 -33
- package/src/queues/plan-agent-heartbeat.queue.ts +111 -83
- package/src/queues/plan-scheduler.queue.ts +101 -97
- package/src/queues/post-chat-memory.queue.ts +56 -46
- package/src/queues/queue-factory.ts +146 -69
- package/src/queues/queues.service.ts +61 -0
- package/src/queues/title-generation.queue.ts +44 -44
- package/src/redis/connection.ts +181 -164
- package/src/redis/org-memory-lock.ts +24 -9
- package/src/redis/redis-lease-lock.ts +8 -1
- package/src/redis/stream-context.ts +17 -9
- package/src/runtime/agent-identity-overrides.ts +7 -3
- package/src/runtime/agent-runtime-policy.ts +10 -5
- package/src/runtime/agent-stream-helpers.ts +24 -15
- package/src/runtime/chat-run-orchestration.ts +1 -1
- package/src/runtime/context-compaction/context-compaction-runtime.ts +28 -32
- package/src/runtime/context-compaction/context-compaction.ts +131 -85
- package/src/runtime/domain-layer.ts +203 -0
- package/src/runtime/execution-plan-visibility.ts +5 -2
- package/src/runtime/graph-designer.ts +0 -14
- package/src/runtime/helper-model.ts +8 -4
- package/src/runtime/index.ts +1 -1
- package/src/runtime/indexed-repositories-policy.ts +2 -6
- package/src/runtime/memory/memory-block.ts +19 -9
- package/src/runtime/memory/memory-pipeline.ts +53 -66
- package/src/runtime/memory/memory-scope.ts +33 -29
- package/src/runtime/plugin-resolution.ts +58 -62
- package/src/runtime/post-turn-side-effects.ts +139 -161
- package/src/runtime/retrieval-adapters.ts +4 -4
- package/src/runtime/runtime-config.ts +3 -9
- package/src/runtime/runtime-extensions.ts +0 -43
- package/src/runtime/runtime-lifecycle.ts +124 -0
- package/src/runtime/runtime-services.ts +455 -0
- package/src/runtime/runtime-worker-registry.ts +113 -30
- package/src/runtime/social-chat/social-chat-agent-runner.ts +13 -8
- package/src/runtime/social-chat/social-chat-history.ts +24 -13
- package/src/runtime/social-chat/social-chat.ts +420 -369
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +64 -57
- package/src/runtime/team-consultation/team-consultation-prompts.ts +11 -6
- package/src/runtime/thread-chat-helpers.ts +18 -9
- package/src/runtime/thread-turn-context.ts +28 -74
- package/src/runtime/turn-lifecycle.ts +6 -14
- package/src/services/agent-activity.service.ts +169 -176
- package/src/services/agent-executor.service.ts +207 -196
- package/src/services/artifact.service.ts +10 -5
- package/src/services/attachment.service.ts +16 -48
- package/src/services/autonomous-job.service.ts +81 -87
- package/src/services/background-work.service.ts +54 -0
- package/src/services/chat-run-registry.service.ts +3 -1
- package/src/services/context-compaction.service.ts +8 -10
- package/src/services/document-chunk.service.ts +8 -17
- package/src/services/execution-plan/execution-plan-graph.ts +122 -109
- package/src/services/execution-plan/execution-plan-schedule.ts +1 -15
- package/src/services/execution-plan/execution-plan.service.ts +68 -51
- package/src/services/feedback-loop.service.ts +1 -1
- package/src/services/global-orchestrator.service.ts +49 -15
- package/src/services/graph-full-routing.ts +49 -37
- package/src/services/index.ts +1 -0
- package/src/services/institutional-memory.service.ts +8 -17
- package/src/services/learned-skill.service.ts +38 -35
- package/src/services/memory/memory-conversation.ts +10 -5
- package/src/services/memory/memory-errors.ts +27 -0
- package/src/services/memory/memory-org-memory.ts +14 -3
- package/src/services/memory/memory-preseeded.ts +10 -4
- package/src/services/memory/memory-utils.ts +2 -1
- package/src/services/memory/memory.service.ts +37 -52
- package/src/services/memory/rerank.service.ts +3 -11
- package/src/services/monitoring-window.service.ts +1 -1
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/node-workspace.service.ts +2 -2
- package/src/services/notification.service.ts +16 -4
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +34 -51
- package/src/services/ownership-dispatcher.service.ts +148 -95
- package/src/services/plan/plan-agent-heartbeat.service.ts +30 -16
- package/src/services/plan/plan-agent-query.service.ts +13 -9
- package/src/services/plan/plan-approval.service.ts +52 -48
- package/src/services/plan/plan-artifact.service.ts +2 -2
- package/src/services/plan/plan-builder.service.ts +2 -2
- package/src/services/plan/plan-checkpoint.service.ts +1 -1
- package/src/services/plan/plan-compiler.service.ts +1 -1
- package/src/services/plan/plan-completion-side-effects.ts +99 -113
- package/src/services/plan/plan-coordination.service.ts +1 -1
- package/src/services/plan/plan-cycle.service.ts +171 -202
- package/src/services/plan/plan-deadline.service.ts +304 -307
- package/src/services/plan/plan-event-delivery.service.ts +84 -72
- package/src/services/plan/plan-executor-context.ts +2 -0
- package/src/services/plan/plan-executor-graph.ts +375 -353
- package/src/services/plan/plan-executor-helpers.ts +60 -75
- package/src/services/plan/plan-executor.service.ts +494 -489
- package/src/services/plan/plan-run.service.ts +12 -19
- package/src/services/plan/plan-scheduler.service.ts +89 -82
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +8 -5
- package/src/services/plan/plan-validator.service.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +17 -11
- package/src/services/plugin-executor.service.ts +26 -21
- package/src/services/quality-metrics.service.ts +1 -1
- package/src/services/queue-job.service.ts +8 -17
- package/src/services/recent-activity-title.service.ts +22 -10
- package/src/services/recent-activity.service.ts +1 -1
- package/src/services/skill-resolver.service.ts +1 -1
- package/src/services/social-chat-history.service.ts +37 -20
- package/src/services/system-executor.service.ts +25 -20
- package/src/services/thread/thread-bootstrap.ts +37 -19
- package/src/services/thread/thread-listing.ts +2 -1
- package/src/services/thread/thread-memory-block.ts +18 -5
- package/src/services/thread/thread-message.service.ts +30 -13
- package/src/services/thread/thread-title.service.ts +1 -1
- package/src/services/thread/thread-turn-execution.ts +87 -83
- package/src/services/thread/thread-turn-preparation.service.ts +65 -40
- package/src/services/thread/thread-turn-streaming.ts +32 -36
- package/src/services/thread/thread-turn.ts +43 -29
- package/src/services/thread/thread.service.ts +32 -8
- package/src/services/user.service.ts +1 -1
- package/src/services/write-intent-validator.service.ts +1 -1
- package/src/storage/attachment-storage.service.ts +7 -4
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +1 -1
- package/src/system-agents/helper-agent-options.ts +1 -1
- package/src/system-agents/memory-reranker.agent.ts +1 -1
- package/src/system-agents/memory.agent.ts +1 -1
- package/src/system-agents/recent-activity-title-refiner.agent.ts +9 -6
- package/src/system-agents/regular-chat-memory-digest.agent.ts +1 -1
- package/src/system-agents/skill-extractor.agent.ts +1 -1
- package/src/system-agents/skill-manager.agent.ts +1 -1
- package/src/system-agents/thread-router.agent.ts +23 -20
- package/src/system-agents/title-generator.agent.ts +1 -1
- package/src/tools/execution-plan.tool.ts +36 -20
- package/src/tools/fetch-webpage.tool.ts +30 -22
- package/src/tools/firecrawl-client.ts +1 -6
- package/src/tools/plan-approval.tool.ts +9 -1
- package/src/tools/remember-memory.tool.ts +3 -6
- package/src/tools/research-topic.tool.ts +12 -3
- package/src/tools/search-web.tool.ts +26 -18
- package/src/tools/search.tool.ts +4 -5
- package/src/tools/team-think.tool.ts +139 -121
- package/src/utils/async.ts +15 -6
- package/src/utils/errors.ts +27 -15
- package/src/workers/bootstrap.ts +34 -58
- package/src/workers/memory-consolidation.worker.ts +4 -1
- package/src/workers/organization-learning.worker.ts +16 -3
- package/src/workers/regular-chat-memory-digest.helpers.ts +3 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +46 -29
- package/src/workers/skill-extraction.runner.ts +13 -15
- package/src/workers/worker-utils.ts +14 -8
- package/src/config/search.ts +0 -3
- package/src/effect/awaitable-effect.ts +0 -87
- package/src/effect/runtime-ref.ts +0 -25
- package/src/effect/runtime.ts +0 -31
- package/src/redis/runtime-connection.ts +0 -10
- package/src/runtime/agent-types.ts +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ConsultTeamArgsSchema, withMessageCreatedAt } from '@lota-sdk/shared'
|
|
2
2
|
import type { ChatMessage, ConsultTeamResultData } from '@lota-sdk/shared'
|
|
3
3
|
import { convertToModelMessages, tool as createTool } from 'ai'
|
|
4
|
-
import { Schema, Effect, Fiber, Queue, Ref } from 'effect'
|
|
4
|
+
import { Schema, Deferred, Effect, Exit, Fiber, Queue, Ref, Scope } from 'effect'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
7
7
|
import { nowEpochMillis } from '../../utils/date-time'
|
|
8
8
|
import { createTimedAbortSignal } from '../agent-stream-helpers'
|
|
9
9
|
import { buildModelInputMessagesWithUploadMetadata, buildReadableUploadMetadataText } from '../chat-attachments'
|
|
@@ -91,6 +91,7 @@ export interface TeamConsultationParticipantRunner {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export interface CreateConsultTeamToolParams {
|
|
94
|
+
agentConfig: ResolvedAgentConfig
|
|
94
95
|
historyMessages: ChatMessage[]
|
|
95
96
|
latestUserMessageId: string
|
|
96
97
|
availableUploads: ReadableUploadMetadataLike[]
|
|
@@ -114,8 +115,6 @@ interface ConsultTeamStreamResources {
|
|
|
114
115
|
workerFiber: Fiber.Fiber<unknown, unknown>
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
type TeamConsultationResourcesError = TeamConsultationError
|
|
118
|
-
|
|
119
118
|
function createConsultTeamStreamResources(params: {
|
|
120
119
|
task: string
|
|
121
120
|
uploadMetadataText: string
|
|
@@ -272,14 +271,17 @@ function createConsultTeamStreamResources(params: {
|
|
|
272
271
|
}
|
|
273
272
|
|
|
274
273
|
class ConsultTeamSnapshotIterable implements AsyncIterableIterator<ConsultTeamResultData> {
|
|
275
|
-
private readonly
|
|
274
|
+
private readonly scope: Scope.Closeable
|
|
275
|
+
private readonly resourcesDeferred: Deferred.Deferred<ConsultTeamStreamResources, TeamConsultationError>
|
|
276
|
+
private readonly buildEffect: Effect.Effect<ConsultTeamStreamResources, TeamConsultationError>
|
|
277
|
+
private initStarted = false
|
|
276
278
|
private closed = false
|
|
277
279
|
private completed = false
|
|
278
280
|
|
|
279
281
|
constructor(params: CreateConsultTeamToolParams, task: string) {
|
|
280
|
-
const teamConsultParticipants =
|
|
282
|
+
const teamConsultParticipants = params.agentConfig.teamConsultParticipants
|
|
281
283
|
const uploadMetadataText = buildReadableUploadMetadataText(params.availableUploads)
|
|
282
|
-
const agentDisplayNames =
|
|
284
|
+
const agentDisplayNames = params.agentConfig.displayNames
|
|
283
285
|
const resolveDisplayName = (agentId: string) => {
|
|
284
286
|
if (params.displayNamesById && Object.hasOwn(params.displayNamesById, agentId)) {
|
|
285
287
|
const override = params.displayNamesById[agentId]
|
|
@@ -291,38 +293,52 @@ class ConsultTeamSnapshotIterable implements AsyncIterableIterator<ConsultTeamRe
|
|
|
291
293
|
return agentDisplayNames[agentId] ?? agentId
|
|
292
294
|
}
|
|
293
295
|
|
|
294
|
-
this.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
)
|
|
296
|
+
this.scope = Scope.makeUnsafe()
|
|
297
|
+
this.resourcesDeferred = Deferred.makeUnsafe<ConsultTeamStreamResources, TeamConsultationError>()
|
|
298
|
+
this.buildEffect = createConsultTeamStreamResources({
|
|
299
|
+
task,
|
|
300
|
+
uploadMetadataText,
|
|
301
|
+
teamConsultParticipants,
|
|
302
|
+
resolveDisplayName,
|
|
303
|
+
historyMessages: params.historyMessages,
|
|
304
|
+
latestUserMessageId: params.latestUserMessageId,
|
|
305
|
+
availableUploads: params.availableUploads,
|
|
306
|
+
systemWorkspaceDetails: params.systemWorkspaceDetails,
|
|
307
|
+
getPreSeededMemoriesSection: params.getPreSeededMemoriesSection,
|
|
308
|
+
retrievedKnowledgeSection: params.retrievedKnowledgeSection,
|
|
309
|
+
abortSignal: params.abortSignal,
|
|
310
|
+
participantRunner: params.participantRunner,
|
|
311
|
+
onReadError: params.onReadError,
|
|
312
|
+
})
|
|
311
313
|
}
|
|
312
314
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
315
|
+
/**
|
|
316
|
+
* Acquire-release: on first call, build the stream resources and register
|
|
317
|
+
* cleanup as a finalizer in the iterable's scope. Subsequent calls await the
|
|
318
|
+
* cached `Deferred`. If init fails, no finalizer is registered, so closing
|
|
319
|
+
* the scope is a no-op for the leaked-resource path.
|
|
320
|
+
*/
|
|
321
|
+
private acquireResourcesEffect(): Effect.Effect<ConsultTeamStreamResources, TeamConsultationError> {
|
|
322
|
+
if (this.initStarted) {
|
|
323
|
+
return Deferred.await(this.resourcesDeferred)
|
|
324
|
+
}
|
|
325
|
+
this.initStarted = true
|
|
326
|
+
|
|
327
|
+
const acquire = Effect.acquireRelease(this.buildEffect, ({ snapshotQueue, workerFiber }) =>
|
|
328
|
+
Fiber.interrupt(workerFiber).pipe(Effect.andThen(Queue.shutdown(snapshotQueue))),
|
|
329
|
+
).pipe(Scope.provide(this.scope))
|
|
330
|
+
|
|
331
|
+
return acquire.pipe(
|
|
332
|
+
Effect.exit,
|
|
333
|
+
Effect.flatMap((exit) =>
|
|
334
|
+
Deferred.done(this.resourcesDeferred, exit).pipe(Effect.andThen(Deferred.await(this.resourcesDeferred))),
|
|
335
|
+
),
|
|
336
|
+
)
|
|
319
337
|
}
|
|
320
338
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
): Effect.Effect<void, never> {
|
|
325
|
-
return Effect.andThen(Fiber.interrupt(workerFiber), Queue.shutdown(snapshotQueue))
|
|
339
|
+
/** Close the scope idempotently. Runs cleanup finalizers iff init succeeded. */
|
|
340
|
+
private closeScopeEffect(): Effect.Effect<void, never> {
|
|
341
|
+
return Scope.close(this.scope, Exit.void).pipe(Effect.catchCause(() => Effect.void))
|
|
326
342
|
}
|
|
327
343
|
|
|
328
344
|
[Symbol.asyncIterator](): AsyncIterableIterator<ConsultTeamResultData> {
|
|
@@ -337,7 +353,7 @@ class ConsultTeamSnapshotIterable implements AsyncIterableIterator<ConsultTeamRe
|
|
|
337
353
|
return Effect.runPromise(
|
|
338
354
|
Effect.gen(
|
|
339
355
|
function* (this: ConsultTeamSnapshotIterable) {
|
|
340
|
-
const { snapshotQueue
|
|
356
|
+
const { snapshotQueue } = yield* this.acquireResourcesEffect()
|
|
341
357
|
|
|
342
358
|
if (this.completed) {
|
|
343
359
|
return { done: true, value: undefined as never }
|
|
@@ -346,46 +362,37 @@ class ConsultTeamSnapshotIterable implements AsyncIterableIterator<ConsultTeamRe
|
|
|
346
362
|
const item = yield* Queue.take(snapshotQueue)
|
|
347
363
|
if (item === DONE) {
|
|
348
364
|
this.completed = true
|
|
349
|
-
|
|
365
|
+
this.closed = true
|
|
366
|
+
yield* this.closeScopeEffect()
|
|
350
367
|
return { done: true, value: undefined as never }
|
|
351
368
|
}
|
|
352
369
|
|
|
353
370
|
return { done: false, value: item }
|
|
354
371
|
}.bind(this),
|
|
372
|
+
).pipe(
|
|
373
|
+
Effect.tapCause(() =>
|
|
374
|
+
Effect.sync(() => {
|
|
375
|
+
this.closed = true
|
|
376
|
+
}).pipe(Effect.andThen(this.closeScopeEffect())),
|
|
377
|
+
),
|
|
355
378
|
),
|
|
356
379
|
)
|
|
357
380
|
}
|
|
358
381
|
|
|
359
382
|
return(): Promise<IteratorResult<ConsultTeamResultData>> {
|
|
360
383
|
this.closed = true
|
|
361
|
-
return Effect.runPromise(
|
|
362
|
-
Effect.gen(
|
|
363
|
-
function* (this: ConsultTeamSnapshotIterable) {
|
|
364
|
-
const { snapshotQueue, workerFiber } = yield* this.initResourcesEffect()
|
|
365
|
-
yield* this.cleanupEffect(snapshotQueue, workerFiber)
|
|
366
|
-
return { done: true, value: undefined as never }
|
|
367
|
-
}.bind(this),
|
|
368
|
-
),
|
|
369
|
-
)
|
|
384
|
+
return Effect.runPromise(this.closeScopeEffect().pipe(Effect.as({ done: true, value: undefined as never })))
|
|
370
385
|
}
|
|
371
386
|
|
|
372
387
|
throw(error: unknown): Promise<never> {
|
|
373
388
|
this.closed = true
|
|
374
|
-
return Effect.runPromise(
|
|
375
|
-
Effect.gen(
|
|
376
|
-
function* (this: ConsultTeamSnapshotIterable) {
|
|
377
|
-
const { snapshotQueue, workerFiber } = yield* this.initResourcesEffect()
|
|
378
|
-
yield* this.cleanupEffect(snapshotQueue, workerFiber)
|
|
379
|
-
return yield* Effect.fail(error as never)
|
|
380
|
-
}.bind(this),
|
|
381
|
-
),
|
|
382
|
-
)
|
|
389
|
+
return Effect.runPromise(this.closeScopeEffect().pipe(Effect.andThen(Effect.fail(error as never))))
|
|
383
390
|
}
|
|
384
391
|
}
|
|
385
392
|
|
|
386
393
|
export function createConsultTeamTool(params: CreateConsultTeamToolParams) {
|
|
387
|
-
const teamConsultParticipants =
|
|
388
|
-
const agentDisplayNames =
|
|
394
|
+
const teamConsultParticipants = params.agentConfig.teamConsultParticipants
|
|
395
|
+
const agentDisplayNames = params.agentConfig.displayNames
|
|
389
396
|
const resolveDisplayName = (agentId: string) => {
|
|
390
397
|
if (params.displayNamesById && Object.hasOwn(params.displayNamesById, agentId)) {
|
|
391
398
|
const override = params.displayNamesById[agentId]
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ResolvedAgentConfig } from '../../config/agent-defaults'
|
|
2
2
|
|
|
3
|
-
function resolveDisplayName(agentId: string): string {
|
|
4
|
-
return
|
|
3
|
+
function resolveDisplayName(agentConfig: ResolvedAgentConfig, agentId: string): string {
|
|
4
|
+
return agentConfig.displayNames[agentId] ?? agentId
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function buildTeamConsultationResponseGuard(params: {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
export function buildTeamConsultationResponseGuard(params: {
|
|
8
|
+
agentConfig: ResolvedAgentConfig
|
|
9
|
+
agentId: string
|
|
10
|
+
task: string
|
|
11
|
+
}) {
|
|
12
|
+
const agentName = resolveDisplayName(params.agentConfig, params.agentId)
|
|
13
|
+
const leadAgentDisplayName =
|
|
14
|
+
params.agentConfig.displayNames[params.agentConfig.leadAgentId] ?? params.agentConfig.leadAgentId
|
|
10
15
|
const mentorConstraint =
|
|
11
16
|
params.agentId === 'mentor'
|
|
12
17
|
? ['- As Mentor, answer as an experienced operator reviewing launch discipline, not as a coach or therapist.']
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { toTimestamp } from '@lota-sdk/shared'
|
|
2
2
|
import type { ChatMessage } from '@lota-sdk/shared'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
5
|
+
import { resolveAgentNameAlias } from '../config/agent-defaults'
|
|
5
6
|
import type { ChatMessageLike, ReadableUploadMetadataLike } from './chat-types'
|
|
6
7
|
|
|
7
8
|
export interface ThreadHistoryMessage {
|
|
@@ -29,13 +30,13 @@ export function readInstructionSections(value: unknown): string[] {
|
|
|
29
30
|
.filter((section) => section.length > 0)
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
function getAgentName(message: ChatMessageLike): string | undefined {
|
|
33
|
+
function getAgentName(agentConfig: ResolvedAgentConfig, message: ChatMessageLike): string | undefined {
|
|
33
34
|
const metadata = message.metadata
|
|
34
35
|
if (!metadata || typeof metadata !== 'object') return undefined
|
|
35
36
|
const value = (metadata as Record<string, unknown>).agentName
|
|
36
37
|
if (typeof value !== 'string' || !value.trim()) return undefined
|
|
37
|
-
const resolvedAgentName = resolveAgentNameAlias(value)
|
|
38
|
-
return resolvedAgentName ? (
|
|
38
|
+
const resolvedAgentName = resolveAgentNameAlias(agentConfig, value)
|
|
39
|
+
return resolvedAgentName ? (agentConfig.displayNames[resolvedAgentName] ?? value.trim()) : value.trim()
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export function extractMessageText(message: ChatMessageLike): string {
|
|
@@ -45,7 +46,11 @@ export function extractMessageText(message: ChatMessageLike): string {
|
|
|
45
46
|
.trim()
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
export function toHistoryMessages(
|
|
49
|
+
export function toHistoryMessages(
|
|
50
|
+
agentConfig: ResolvedAgentConfig,
|
|
51
|
+
messages: ChatMessageLike[],
|
|
52
|
+
maxItems = 24,
|
|
53
|
+
): ThreadHistoryMessage[] {
|
|
49
54
|
return messages
|
|
50
55
|
.map((message): ThreadHistoryMessage | null => {
|
|
51
56
|
const content = extractMessageText(message)
|
|
@@ -55,7 +60,7 @@ export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24): T
|
|
|
55
60
|
return { role: 'user', content }
|
|
56
61
|
}
|
|
57
62
|
if (message.role === 'assistant') {
|
|
58
|
-
const agentName = getAgentName(message)
|
|
63
|
+
const agentName = getAgentName(agentConfig, message)
|
|
59
64
|
return { role: 'agent', content, ...(agentName ? { agentName } : {}) }
|
|
60
65
|
}
|
|
61
66
|
return null
|
|
@@ -65,6 +70,7 @@ export function toHistoryMessages(messages: ChatMessageLike[], maxItems = 24): T
|
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
export function buildConversationSummary(params: {
|
|
73
|
+
agentConfig: ResolvedAgentConfig
|
|
68
74
|
userMessageText: string
|
|
69
75
|
assistantMessages: ChatMessageLike[]
|
|
70
76
|
}): string {
|
|
@@ -76,15 +82,18 @@ export function buildConversationSummary(params: {
|
|
|
76
82
|
for (const message of params.assistantMessages) {
|
|
77
83
|
const content = extractMessageText(message)
|
|
78
84
|
if (!content) continue
|
|
79
|
-
const agentName = getAgentName(message)
|
|
85
|
+
const agentName = getAgentName(params.agentConfig, message)
|
|
80
86
|
lines.push(agentName ? `${agentName}: ${content}` : `Assistant: ${content}`)
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
return lines.join('\n\n').trim()
|
|
84
90
|
}
|
|
85
91
|
|
|
86
|
-
export function buildAgentHistoryMessages(
|
|
87
|
-
|
|
92
|
+
export function buildAgentHistoryMessages(
|
|
93
|
+
agentConfig: ResolvedAgentConfig,
|
|
94
|
+
messages: ChatMessageLike[],
|
|
95
|
+
): Array<{ content: string; agentName?: string }> {
|
|
96
|
+
return toHistoryMessages(agentConfig, messages)
|
|
88
97
|
.filter((message) => message.role === 'agent')
|
|
89
98
|
.map((message) => ({ content: message.content, ...(message.agentName ? { agentName: message.agentName } : {}) }))
|
|
90
99
|
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { Schema, Effect } from 'effect'
|
|
2
2
|
|
|
3
3
|
import type { RecordIdRef } from '../db/record-id'
|
|
4
|
-
import {
|
|
5
|
-
import { TABLES } from '../db/tables'
|
|
6
|
-
import {
|
|
7
|
-
effectTryMaybeAsync as effectTryMaybeAsyncShared,
|
|
8
|
-
effectTryPromise as effectTryPromiseShared,
|
|
9
|
-
} from '../effect/helpers'
|
|
4
|
+
import { effectTryMaybeAsync as effectTryMaybeAsyncShared, makeEffectTryPromiseWithMessage } from '../effect/helpers'
|
|
10
5
|
import { buildAgentPromptContext } from './agent-prompt-context'
|
|
11
6
|
import {
|
|
12
7
|
buildIndexedRepositoriesContext,
|
|
@@ -14,10 +9,9 @@ import {
|
|
|
14
9
|
getLinearInstallationByOrgId,
|
|
15
10
|
} from './plugin-resolution'
|
|
16
11
|
import type {
|
|
12
|
+
LotaRuntimeAdapters,
|
|
17
13
|
LotaRuntimeIndexedRepositoriesContext,
|
|
18
14
|
LotaRuntimeTurnHooks,
|
|
19
|
-
LotaRuntimeWorkspaceLifecycleState,
|
|
20
|
-
LotaRuntimeWorkspaceProjectionState,
|
|
21
15
|
LotaRuntimeWorkspaceProvider,
|
|
22
16
|
} from './runtime-extensions'
|
|
23
17
|
import { readInstructionSections, readOptionalString } from './thread-chat-helpers'
|
|
@@ -35,9 +29,9 @@ class ThreadTurnContextError extends Schema.TaggedErrorClass<ThreadTurnContextEr
|
|
|
35
29
|
cause: Schema.optional(Schema.Defect),
|
|
36
30
|
}) {}
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
const effectTryPromise = makeEffectTryPromiseWithMessage(
|
|
33
|
+
(message, cause) => new ThreadTurnContextError({ message, cause }),
|
|
34
|
+
)
|
|
41
35
|
|
|
42
36
|
function effectTryMaybeAsync<A>(
|
|
43
37
|
evaluate: () => A | PromiseLike<A>,
|
|
@@ -46,21 +40,7 @@ function effectTryMaybeAsync<A>(
|
|
|
46
40
|
return effectTryMaybeAsyncShared(evaluate, (cause) => new ThreadTurnContextError({ message, cause }))
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
workspace: Record<string, unknown>
|
|
51
|
-
workspaceLifecycleState: LotaRuntimeWorkspaceLifecycleState | undefined
|
|
52
|
-
workspaceProfileState: LotaRuntimeWorkspaceProjectionState | undefined
|
|
53
|
-
onboardingActive: boolean
|
|
54
|
-
linearInstalled: boolean
|
|
55
|
-
githubInstalled: boolean
|
|
56
|
-
indexedRepoContext: LotaRuntimeIndexedRepositoriesContext
|
|
57
|
-
promptContext: { systemWorkspaceDetails?: string }
|
|
58
|
-
retrievedKnowledgeSection: string | undefined
|
|
59
|
-
buildContextResult: Record<string, unknown> | null
|
|
60
|
-
hookInstructionSections: string[]
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(function* (params: {
|
|
43
|
+
export const assembleThreadTurnContext = Effect.fn('ThreadTurnContext.assemble')(function* (params: {
|
|
64
44
|
thread: unknown
|
|
65
45
|
threadRef: RecordIdRef
|
|
66
46
|
orgRef: RecordIdRef
|
|
@@ -72,6 +52,8 @@ const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(
|
|
|
72
52
|
workspacePromise: Promise<Record<string, unknown>>
|
|
73
53
|
workspaceProvider?: LotaRuntimeWorkspaceProvider
|
|
74
54
|
turnHooks: LotaRuntimeTurnHooks
|
|
55
|
+
runtimeAdapters: LotaRuntimeAdapters
|
|
56
|
+
pluginRuntime?: Record<string, unknown>
|
|
75
57
|
}) {
|
|
76
58
|
const workspace = yield* effectTryPromise(() => params.workspacePromise, 'Failed to load thread workspace').pipe(
|
|
77
59
|
Effect.withSpan('ThreadTurnContext.loadWorkspace'),
|
|
@@ -88,21 +70,21 @@ const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(
|
|
|
88
70
|
|
|
89
71
|
const onboardingActive = workspaceLifecycleState?.bootstrapActive ?? false
|
|
90
72
|
const linearInstallation = yield* effectTryPromise(
|
|
91
|
-
() => getLinearInstallationByOrgId(params.orgRef),
|
|
73
|
+
() => getLinearInstallationByOrgId(params.pluginRuntime, params.orgRef),
|
|
92
74
|
'Failed to load Linear installation',
|
|
93
75
|
).pipe(
|
|
94
76
|
Effect.catch(() => Effect.succeed(null)),
|
|
95
77
|
Effect.withSpan('ThreadTurnContext.loadLinearInstallation'),
|
|
96
78
|
)
|
|
97
79
|
const githubInstallation = yield* effectTryPromise(
|
|
98
|
-
() => getGithubInstallationForOrganization(params.orgIdString),
|
|
80
|
+
() => getGithubInstallationForOrganization(params.pluginRuntime, params.orgIdString),
|
|
99
81
|
'Failed to load GitHub installation',
|
|
100
82
|
).pipe(
|
|
101
83
|
Effect.catch(() => Effect.succeed(null)),
|
|
102
84
|
Effect.withSpan('ThreadTurnContext.loadGithubInstallation'),
|
|
103
85
|
)
|
|
104
86
|
const indexedRepoContext = yield* effectTryPromise(
|
|
105
|
-
() => buildIndexedRepositoriesContext(params.orgIdString),
|
|
87
|
+
() => buildIndexedRepositoriesContext(params.runtimeAdapters, params.orgIdString),
|
|
106
88
|
'Failed to build indexed repository context',
|
|
107
89
|
).pipe(
|
|
108
90
|
Effect.catch(() =>
|
|
@@ -129,16 +111,16 @@ const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(
|
|
|
129
111
|
Effect.withSpan('ThreadTurnContext.buildPromptSummary'),
|
|
130
112
|
)
|
|
131
113
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
114
|
+
const initialLinearInstalled = Boolean(linearInstallation)
|
|
115
|
+
const initialGithubInstalled = Boolean(githubInstallation)
|
|
116
|
+
const initialPromptContext = buildAgentPromptContext({
|
|
135
117
|
workspaceName: workspaceProfileState?.workspaceName ?? readOptionalString(workspace.name) ?? undefined,
|
|
136
118
|
summaryBlock: workspaceProfileState?.summaryBlock,
|
|
137
119
|
promptSummary,
|
|
138
120
|
userName: params.userName ?? undefined,
|
|
139
121
|
recentDomainEvents,
|
|
140
122
|
})
|
|
141
|
-
|
|
123
|
+
const initialRetrievedKnowledgeSection: string | undefined = !params.messageText
|
|
142
124
|
? undefined
|
|
143
125
|
: yield* effectTryMaybeAsync(
|
|
144
126
|
() =>
|
|
@@ -161,36 +143,33 @@ const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(
|
|
|
161
143
|
workspace,
|
|
162
144
|
onboardingActive,
|
|
163
145
|
messageText: params.messageText,
|
|
164
|
-
linearInstalled,
|
|
165
|
-
githubInstalled,
|
|
146
|
+
linearInstalled: initialLinearInstalled,
|
|
147
|
+
githubInstalled: initialGithubInstalled,
|
|
166
148
|
indexedRepoContext,
|
|
167
|
-
promptContext,
|
|
149
|
+
promptContext: initialPromptContext,
|
|
168
150
|
workspaceLifecycleState,
|
|
169
151
|
workspaceProfileState,
|
|
170
152
|
promptSummary,
|
|
171
153
|
recentDomainEvents,
|
|
172
|
-
retrievedKnowledgeSection,
|
|
154
|
+
retrievedKnowledgeSection: initialRetrievedKnowledgeSection,
|
|
173
155
|
}),
|
|
174
156
|
'Failed to build thread context',
|
|
175
157
|
).pipe(Effect.withSpan('ThreadTurnContext.buildContextHook'))
|
|
176
158
|
const buildContextResult = isRecord(buildContextResultValue) ? buildContextResultValue : null
|
|
177
159
|
|
|
178
160
|
const buildContextPromptDetails = readOptionalString(buildContextResult?.systemWorkspaceDetails)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
161
|
+
const promptContext = buildContextPromptDetails
|
|
162
|
+
? { systemWorkspaceDetails: buildContextPromptDetails }
|
|
163
|
+
: initialPromptContext
|
|
182
164
|
const buildContextRetrievedKnowledge = readOptionalString(buildContextResult?.retrievedKnowledgeSection)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
165
|
+
const retrievedKnowledgeSection =
|
|
166
|
+
buildContextRetrievedKnowledge !== undefined ? buildContextRetrievedKnowledge : initialRetrievedKnowledgeSection
|
|
186
167
|
const buildContextLinearInstalled = readOptionalBoolean(buildContextResult?.linearInstalled)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
168
|
+
const linearInstalled =
|
|
169
|
+
buildContextLinearInstalled !== undefined ? buildContextLinearInstalled : initialLinearInstalled
|
|
190
170
|
const buildContextGithubInstalled = readOptionalBoolean(buildContextResult?.githubInstalled)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
171
|
+
const githubInstalled =
|
|
172
|
+
buildContextGithubInstalled !== undefined ? buildContextGithubInstalled : initialGithubInstalled
|
|
194
173
|
|
|
195
174
|
const hookInstructionSections = readInstructionSections(
|
|
196
175
|
yield* effectTryMaybeAsync(
|
|
@@ -233,28 +212,3 @@ const assembleThreadTurnContextEffect = Effect.fn('ThreadTurnContext.assemble')(
|
|
|
233
212
|
hookInstructionSections,
|
|
234
213
|
}
|
|
235
214
|
})
|
|
236
|
-
|
|
237
|
-
export function assembleThreadTurnContext(params: {
|
|
238
|
-
thread: unknown
|
|
239
|
-
threadRef: RecordIdRef
|
|
240
|
-
orgRef: RecordIdRef
|
|
241
|
-
userRef: RecordIdRef
|
|
242
|
-
userName?: string | null
|
|
243
|
-
orgIdString: string
|
|
244
|
-
userIdString: string
|
|
245
|
-
messageText: string
|
|
246
|
-
workspacePromise: Promise<Record<string, unknown>>
|
|
247
|
-
workspaceProvider?: LotaRuntimeWorkspaceProvider
|
|
248
|
-
turnHooks: LotaRuntimeTurnHooks
|
|
249
|
-
}): Promise<AssembledThreadTurnContext> {
|
|
250
|
-
return Effect.runPromise(
|
|
251
|
-
assembleThreadTurnContextEffect(params).pipe(
|
|
252
|
-
Effect.annotateSpans({
|
|
253
|
-
threadId: recordIdToString(params.threadRef, TABLES.THREAD),
|
|
254
|
-
orgId: params.orgIdString,
|
|
255
|
-
userId: params.userIdString,
|
|
256
|
-
messageLength: params.messageText.length,
|
|
257
|
-
}),
|
|
258
|
-
),
|
|
259
|
-
)
|
|
260
|
-
}
|
|
@@ -86,17 +86,9 @@ export function finalizeTurnRunEffect(params: {
|
|
|
86
86
|
})
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
unregisterRun: (runId: string) => void
|
|
96
|
-
clearActiveRunId: (runId: string) => MaybeEffect<void>
|
|
97
|
-
disposeAbort: () => void
|
|
98
|
-
activeStreamId?: string
|
|
99
|
-
clearActiveStreamId?: (streamId: string) => MaybeEffect<void>
|
|
100
|
-
}): Promise<void> {
|
|
101
|
-
return Effect.runPromise(finalizeTurnRunEffect(params))
|
|
102
|
-
}
|
|
89
|
+
/**
|
|
90
|
+
* Alias for `finalizeTurnRunEffect`. Kept as the public name consumers use.
|
|
91
|
+
* Callers pipe the returned Effect through their own runtime rather than
|
|
92
|
+
* relying on a process-wide promise adapter.
|
|
93
|
+
*/
|
|
94
|
+
export { finalizeTurnRunEffect as finalizeTurnRun }
|