@lota-sdk/core 0.4.13 → 0.4.14
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 +4 -4
- package/src/ai/embedding-cache.ts +17 -11
- package/src/ai-gateway/ai-gateway.ts +164 -94
- package/src/ai-gateway/index.ts +4 -1
- package/src/config/agent-defaults.ts +2 -2
- package/src/config/agent-types.ts +1 -1
- package/src/create-runtime.ts +259 -200
- package/src/db/cursor-pagination.ts +2 -9
- package/src/db/memory-store.ts +194 -175
- package/src/db/memory.ts +125 -71
- package/src/db/schema-fingerprint.ts +5 -4
- package/src/db/service-normalization.ts +4 -3
- package/src/db/service.ts +3 -2
- package/src/db/startup.ts +15 -16
- package/src/effect/errors.ts +161 -21
- package/src/effect/index.ts +0 -1
- package/src/embeddings/provider.ts +15 -7
- package/src/queues/autonomous-job.queue.ts +10 -22
- package/src/queues/delayed-node-promotion.queue.ts +8 -14
- package/src/queues/document-processor.queue.ts +13 -4
- package/src/queues/memory-consolidation.queue.ts +26 -14
- package/src/queues/plan-agent-heartbeat.queue.ts +10 -9
- package/src/queues/plan-scheduler.queue.ts +37 -15
- package/src/queues/queue-factory.ts +59 -35
- package/src/queues/standalone-worker.ts +3 -2
- package/src/redis/connection.ts +10 -3
- package/src/redis/org-memory-lock.ts +1 -1
- package/src/redis/redis-lease-lock.ts +5 -5
- package/src/redis/stream-context.ts +1 -1
- package/src/runtime/chat-message.ts +64 -1
- package/src/runtime/chat-run-orchestration.ts +33 -20
- package/src/runtime/context-compaction/context-compaction-runtime.ts +14 -7
- package/src/runtime/context-compaction/context-compaction.ts +78 -66
- package/src/runtime/domain-layer.ts +13 -7
- package/src/runtime/execution-plan.ts +7 -3
- package/src/runtime/memory/memory-block.ts +3 -9
- package/src/runtime/memory/memory-scope.ts +3 -1
- package/src/runtime/plugin-resolution.ts +2 -1
- package/src/runtime/post-turn-side-effects.ts +6 -5
- package/src/runtime/retrieval-adapters.ts +8 -20
- package/src/runtime/runtime-config.ts +3 -9
- package/src/runtime/runtime-extensions.ts +2 -4
- package/src/runtime/runtime-lifecycle.ts +56 -16
- package/src/runtime/runtime-services.ts +180 -102
- package/src/runtime/runtime-worker-registry.ts +3 -1
- package/src/runtime/social-chat/social-chat-agent-runner.ts +1 -1
- package/src/runtime/social-chat/social-chat-history.ts +21 -18
- package/src/runtime/social-chat/social-chat.ts +356 -223
- package/src/runtime/specialist-runner.ts +3 -1
- package/src/runtime/team-consultation/team-consultation-orchestrator.ts +3 -2
- package/src/runtime/thread-turn-context.ts +142 -102
- package/src/runtime/turn-lifecycle.ts +15 -46
- package/src/services/agent-activity.service.ts +1 -1
- package/src/services/agent-executor.service.ts +107 -77
- package/src/services/autonomous-job.service.ts +354 -293
- package/src/services/background-work.service.ts +3 -3
- package/src/services/context-compaction.service.ts +7 -2
- package/src/services/document-chunk.service.ts +50 -32
- package/src/services/execution-plan/execution-plan-schedule.ts +5 -3
- package/src/services/execution-plan/execution-plan.service.ts +162 -179
- package/src/services/feedback-loop.service.ts +5 -4
- package/src/services/graph-full-routing.ts +37 -36
- package/src/services/institutional-memory.service.ts +28 -30
- package/src/services/learned-skill.service.ts +107 -72
- package/src/services/memory/memory-errors.ts +4 -23
- package/src/services/memory/memory-org-memory.ts +10 -5
- package/src/services/memory/memory-rerank.ts +18 -6
- package/src/services/memory/memory.service.ts +170 -111
- package/src/services/memory/rerank.service.ts +29 -20
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +69 -75
- package/src/services/ownership-dispatcher.service.ts +40 -39
- package/src/services/plan/plan-agent-heartbeat.service.ts +26 -23
- package/src/services/plan/plan-agent-query.service.ts +39 -31
- package/src/services/plan/plan-completion-side-effects.ts +13 -17
- package/src/services/plan/plan-coordination.service.ts +2 -1
- package/src/services/plan/plan-cycle.service.ts +6 -5
- package/src/services/plan/plan-deadline.service.ts +57 -54
- package/src/services/plan/plan-event-delivery.service.ts +5 -4
- package/src/services/plan/plan-executor-graph.ts +18 -15
- package/src/services/plan/plan-executor.service.ts +235 -262
- package/src/services/plan/plan-run.service.ts +169 -93
- package/src/services/plan/plan-scheduler.service.ts +192 -202
- package/src/services/plan/plan-template.service.ts +1 -1
- package/src/services/plan/plan-transaction-events.ts +1 -1
- package/src/services/plan/plan-workspace.service.ts +23 -14
- package/src/services/plugin-executor.service.ts +5 -9
- package/src/services/queue-job.service.ts +117 -59
- package/src/services/recent-activity-title.service.ts +13 -12
- package/src/services/recent-activity.service.ts +6 -1
- package/src/services/social-chat-history.service.ts +29 -25
- package/src/services/system-executor.service.ts +5 -9
- package/src/services/thread/thread-active-run.ts +2 -2
- package/src/services/thread/thread-listing.ts +61 -57
- package/src/services/thread/thread-memory-block.ts +73 -48
- package/src/services/thread/thread-message.service.ts +76 -65
- package/src/services/thread/thread-record-store.ts +8 -8
- package/src/services/thread/thread-title.service.ts +10 -4
- package/src/services/thread/thread-turn-execution.ts +43 -45
- package/src/services/thread/thread-turn-preparation.service.ts +257 -135
- package/src/services/thread/thread-turn-streaming.ts +82 -85
- package/src/services/thread/thread-turn.ts +8 -8
- package/src/services/thread/thread.service.ts +135 -100
- package/src/services/user.service.ts +45 -48
- package/src/storage/attachment-parser.ts +6 -2
- package/src/storage/attachment-storage.service.ts +5 -6
- package/src/storage/generated-document-storage.service.ts +1 -1
- package/src/system-agents/context-compaction.agent.ts +10 -9
- package/src/system-agents/delegated-agent-factory.ts +30 -6
- package/src/system-agents/memory-reranker.agent.ts +10 -9
- package/src/system-agents/memory.agent.ts +10 -9
- package/src/system-agents/recent-activity-title-refiner.agent.ts +13 -15
- package/src/system-agents/regular-chat-memory-digest.agent.ts +13 -12
- package/src/system-agents/skill-extractor.agent.ts +13 -12
- package/src/system-agents/skill-manager.agent.ts +13 -12
- package/src/system-agents/thread-router.agent.ts +10 -5
- package/src/system-agents/title-generator.agent.ts +13 -12
- package/src/tools/fetch-webpage.tool.ts +13 -13
- package/src/tools/memory-block.tool.ts +3 -1
- package/src/tools/plan-approval.tool.ts +4 -2
- package/src/tools/read-file-parts.tool.ts +10 -4
- package/src/tools/remember-memory.tool.ts +3 -1
- package/src/tools/research-topic.tool.ts +9 -5
- package/src/tools/search-web.tool.ts +16 -16
- package/src/tools/search.tool.ts +20 -5
- package/src/tools/team-think.tool.ts +61 -38
- package/src/utils/async.ts +5 -5
- package/src/utils/errors.ts +19 -18
- package/src/utils/sse-keepalive.ts +28 -25
- package/src/workers/bootstrap.ts +75 -11
- package/src/workers/memory-consolidation.worker.ts +82 -91
- package/src/workers/organization-learning.worker.ts +14 -4
- package/src/workers/regular-chat-memory-digest.runner.ts +105 -67
- package/src/workers/skill-extraction.runner.ts +97 -61
- package/src/workers/utils/repo-structure-extractor.ts +13 -8
- package/src/workers/utils/thread-message-query.ts +24 -24
- package/src/workers/worker-utils.ts +23 -4
- package/src/effect/helpers.ts +0 -123
|
@@ -6,7 +6,7 @@ import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
|
6
6
|
import type { RecordIdInput } from '../db/record-id'
|
|
7
7
|
import type { SurrealDBService } from '../db/service'
|
|
8
8
|
import { TABLES } from '../db/tables'
|
|
9
|
-
import { NotFoundError } from '../effect/errors'
|
|
9
|
+
import { ERROR_TAGS, NotFoundError } from '../effect/errors'
|
|
10
10
|
import { DatabaseServiceTag } from '../effect/services'
|
|
11
11
|
import { toIsoDateTimeString } from '../utils/date-time'
|
|
12
12
|
|
|
@@ -28,7 +28,7 @@ function userNotFoundError(userId: RecordIdInput): NotFoundError {
|
|
|
28
28
|
})
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
class UserServiceError extends Schema.TaggedErrorClass<UserServiceError>()(
|
|
31
|
+
class UserServiceError extends Schema.TaggedErrorClass<UserServiceError>()(ERROR_TAGS.UserServiceError, {
|
|
32
32
|
operation: Schema.String,
|
|
33
33
|
cause: Schema.Defect,
|
|
34
34
|
}) {}
|
|
@@ -38,59 +38,56 @@ function toUserServiceError(operation: string, cause: unknown): UserServiceError
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function makeUserService(db: SurrealDBService) {
|
|
41
|
-
function
|
|
41
|
+
const upsertUser = Effect.fn('UserService.upsertUser')(function* (params: {
|
|
42
|
+
id: RecordIdInput
|
|
43
|
+
name: string
|
|
44
|
+
email: string
|
|
45
|
+
}) {
|
|
42
46
|
const userRef = ensureRecordId(params.id, TABLES.USER)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Effect.
|
|
46
|
-
)
|
|
47
|
-
}
|
|
47
|
+
const record = yield* db
|
|
48
|
+
.upsert(TABLES.USER, userRef, { name: params.name, email: params.email }, sdkUserRecordSchema)
|
|
49
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('upsertUser', cause)))
|
|
50
|
+
return toPublic(record)
|
|
51
|
+
})
|
|
48
52
|
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Effect.
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
}
|
|
53
|
+
const getUser = Effect.fn('UserService.getUser')(function* (userId: RecordIdInput) {
|
|
54
|
+
const record = yield* db
|
|
55
|
+
.findOne(TABLES.USER, { id: ensureRecordId(userId, TABLES.USER) }, sdkUserRecordSchema)
|
|
56
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('getUser', cause)))
|
|
57
|
+
if (!record) return yield* userNotFoundError(userId)
|
|
58
|
+
return toPublic(record)
|
|
59
|
+
})
|
|
56
60
|
|
|
57
|
-
function
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
Effect.
|
|
61
|
-
)
|
|
62
|
-
}
|
|
61
|
+
const listUsers = Effect.fn('UserService.listUsers')(function* () {
|
|
62
|
+
const records = yield* db
|
|
63
|
+
.findMany(TABLES.USER, {}, sdkUserRecordSchema, { orderBy: 'createdAt', orderDir: 'ASC' })
|
|
64
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('listUsers', cause)))
|
|
65
|
+
return records.map(toPublic)
|
|
66
|
+
})
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const updateUser = Effect.fn('UserService.updateUser')(function* (
|
|
69
|
+
userId: RecordIdInput,
|
|
70
|
+
params: { name?: string; email?: string },
|
|
71
|
+
) {
|
|
72
|
+
const updated = yield* db
|
|
73
|
+
.update(TABLES.USER, ensureRecordId(userId, TABLES.USER), params, sdkUserRecordSchema)
|
|
74
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('updateUser', cause)))
|
|
75
|
+
if (!updated) return yield* userNotFoundError(userId)
|
|
76
|
+
return toPublic(updated)
|
|
77
|
+
})
|
|
71
78
|
|
|
72
|
-
function
|
|
79
|
+
const deleteUser = Effect.fn('UserService.deleteUser')(function* (userId: RecordIdInput) {
|
|
73
80
|
const userRef = ensureRecordId(userId, TABLES.USER)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return yield* userNotFoundError(userId)
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
}
|
|
81
|
+
yield* db
|
|
82
|
+
.deleteWhere(TABLES.ORGANIZATION_MEMBER, { in: userRef })
|
|
83
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('deleteUser.deleteMemberships', cause)))
|
|
84
|
+
const deleted = yield* db
|
|
85
|
+
.deleteById(TABLES.USER, userRef)
|
|
86
|
+
.pipe(Effect.mapError((cause) => toUserServiceError('deleteUser.deleteUser', cause)))
|
|
87
|
+
if (!deleted) return yield* userNotFoundError(userId)
|
|
88
|
+
})
|
|
86
89
|
|
|
87
|
-
return {
|
|
88
|
-
upsertUser: upsertUserEffect,
|
|
89
|
-
getUser: getUserEffect,
|
|
90
|
-
listUsers: listUsersEffect,
|
|
91
|
-
updateUser: updateUserEffect,
|
|
92
|
-
deleteUser: deleteUserEffect,
|
|
93
|
-
}
|
|
90
|
+
return { upsertUser, getUser, listUsers, updateUser, deleteUser }
|
|
94
91
|
}
|
|
95
92
|
|
|
96
93
|
export class UserServiceTag extends Context.Service<UserServiceTag, ReturnType<typeof makeUserService>>()(
|
|
@@ -3,9 +3,11 @@ import { Schema, Effect } from 'effect'
|
|
|
3
3
|
import mammoth from 'mammoth'
|
|
4
4
|
import { PDFParse } from 'pdf-parse'
|
|
5
5
|
|
|
6
|
+
import { ERROR_TAGS } from '../effect/errors'
|
|
7
|
+
|
|
6
8
|
const READ_FILE_PARTS_CHARS_PER_PAGE = 3500
|
|
7
9
|
|
|
8
|
-
class AttachmentParserError extends Schema.TaggedErrorClass<AttachmentParserError>()(
|
|
10
|
+
class AttachmentParserError extends Schema.TaggedErrorClass<AttachmentParserError>()(ERROR_TAGS.AttachmentParserError, {
|
|
9
11
|
message: Schema.String,
|
|
10
12
|
cause: Schema.Defect,
|
|
11
13
|
}) {}
|
|
@@ -67,7 +69,9 @@ export function extractPdfPages(file: File): Promise<string[]> {
|
|
|
67
69
|
}).pipe(
|
|
68
70
|
Effect.ensuring(
|
|
69
71
|
tryAttachmentPromise('Failed to destroy PDF parser.', () => parser.destroy()).pipe(
|
|
70
|
-
Effect.
|
|
72
|
+
Effect.catchTag(ERROR_TAGS.AttachmentParserError, (error) =>
|
|
73
|
+
Effect.logWarning(`Attachment parser cleanup failed: ${error.message}`),
|
|
74
|
+
),
|
|
71
75
|
Effect.asVoid,
|
|
72
76
|
),
|
|
73
77
|
),
|
|
@@ -3,7 +3,7 @@ import { S3Client } from 'bun'
|
|
|
3
3
|
import { Context, Schema, Effect, Layer } from 'effect'
|
|
4
4
|
|
|
5
5
|
import { serverLogger } from '../config/logger'
|
|
6
|
-
import { BadRequestError, ForbiddenError } from '../effect/errors'
|
|
6
|
+
import { ERROR_TAGS, BadRequestError, ForbiddenError } from '../effect/errors'
|
|
7
7
|
import { RuntimeConfigServiceTag } from '../effect/services'
|
|
8
8
|
import type { ResolvedLotaRuntimeConfig } from '../runtime/runtime-config'
|
|
9
9
|
import { getErrorMessage } from '../utils/errors'
|
|
@@ -36,11 +36,10 @@ export type UploadedThreadAttachment = {
|
|
|
36
36
|
|
|
37
37
|
type AttachmentContextCandidate = { storageKey: string; name: string; contentType: string; sizeBytes: number | null }
|
|
38
38
|
|
|
39
|
-
class AttachmentStorageError extends Schema.TaggedErrorClass<AttachmentStorageError>()(
|
|
40
|
-
|
|
41
|
-
message: Schema.String,
|
|
42
|
-
|
|
43
|
-
}) {}
|
|
39
|
+
class AttachmentStorageError extends Schema.TaggedErrorClass<AttachmentStorageError>()(
|
|
40
|
+
ERROR_TAGS.AttachmentStorageError,
|
|
41
|
+
{ operation: Schema.String, message: Schema.String, cause: Schema.Defect },
|
|
42
|
+
) {}
|
|
44
43
|
|
|
45
44
|
function toAttachmentStorageError(operation: string, cause: unknown): AttachmentStorageError {
|
|
46
45
|
return new AttachmentStorageError({ operation, message: getErrorMessage(cause), cause })
|
|
@@ -26,7 +26,7 @@ function buildGeneratedDocumentStorageKey(params: {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
class GeneratedDocumentStorageError extends Schema.TaggedErrorClass<GeneratedDocumentStorageError>()(
|
|
29
|
-
'GeneratedDocumentStorageError',
|
|
29
|
+
'@lota-sdk/core/GeneratedDocumentStorageError',
|
|
30
30
|
{ message: Schema.String, cause: Schema.Defect },
|
|
31
31
|
) {}
|
|
32
32
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
5
5
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
6
6
|
import {
|
|
7
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -31,12 +31,13 @@ The caller enforces a structured output schema with exactly one field:
|
|
|
31
31
|
</output-format>
|
|
32
32
|
</agent-instructions>`
|
|
33
33
|
|
|
34
|
-
export function
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
export function makeContextCompactionAgentFactory(models: AiGatewayModels) {
|
|
35
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
36
|
+
new ToolLoopAgent({
|
|
37
|
+
id: 'context-compaction',
|
|
38
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
39
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
40
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
41
|
+
...resolveHelperAgentOptions(options, { instructions: CONTEXT_COMPACTION_PROMPT }),
|
|
42
|
+
})
|
|
42
43
|
}
|
|
@@ -5,6 +5,7 @@ import { z } from 'zod'
|
|
|
5
5
|
|
|
6
6
|
import type { ToolDefinition } from '../ai/definitions'
|
|
7
7
|
import { aiLogger } from '../config/logger'
|
|
8
|
+
import { ERROR_TAGS } from '../effect/errors'
|
|
8
9
|
import { formatUtcPromptDate, nowDate } from '../utils/date-time'
|
|
9
10
|
import { getErrorMessage } from '../utils/errors'
|
|
10
11
|
import { isRecord } from '../utils/string'
|
|
@@ -12,6 +13,7 @@ import { assertSubstantiveAgentResult } from './agent-result'
|
|
|
12
13
|
|
|
13
14
|
type AgentProviderOptions = ToolLoopAgentSettings['providerOptions']
|
|
14
15
|
type AgentModel = LanguageModel | (() => LanguageModel)
|
|
16
|
+
type AgentModelWithContext<TContext> = LanguageModel | ((context: TContext) => LanguageModel)
|
|
15
17
|
|
|
16
18
|
interface DelegatedAgentDefinition {
|
|
17
19
|
id: string
|
|
@@ -24,13 +26,26 @@ interface DelegatedAgentDefinition {
|
|
|
24
26
|
maxSteps?: number
|
|
25
27
|
maxOutputTokens?: number
|
|
26
28
|
temperature?: number
|
|
29
|
+
runPromise: <A, E>(effect: Effect.Effect<A, E, never>, options?: { signal?: AbortSignal }) => Promise<A>
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
type DelegatedAgentRunPromise = <A, E>(
|
|
33
|
+
effect: Effect.Effect<A, E, never>,
|
|
34
|
+
options?: { signal?: AbortSignal },
|
|
35
|
+
) => Promise<A>
|
|
36
|
+
|
|
37
|
+
interface DelegatedAgentDefinitionWithContext<TContext> extends Omit<
|
|
38
|
+
DelegatedAgentDefinition,
|
|
39
|
+
'tools' | 'model' | 'runPromise'
|
|
40
|
+
> {
|
|
41
|
+
model: AgentModelWithContext<TContext>
|
|
30
42
|
createTools: (context: TContext) => ToolSet
|
|
43
|
+
/** Pull runPromise off the caller's context so each tool invocation carries
|
|
44
|
+
* its own runtime binding rather than closing over a boot-time one. */
|
|
45
|
+
getRunPromise: (context: TContext) => DelegatedAgentRunPromise
|
|
31
46
|
}
|
|
32
47
|
|
|
33
|
-
class DelegatedAgentError extends Schema.TaggedErrorClass<DelegatedAgentError>()(
|
|
48
|
+
class DelegatedAgentError extends Schema.TaggedErrorClass<DelegatedAgentError>()(ERROR_TAGS.DelegatedAgentError, {
|
|
34
49
|
stage: Schema.Literals(['generate', 'validate', 'follow-up-generate', 'follow-up-validate']),
|
|
35
50
|
label: Schema.String,
|
|
36
51
|
message: Schema.String,
|
|
@@ -49,6 +64,13 @@ function resolveAgentModel(model: AgentModel): LanguageModel {
|
|
|
49
64
|
return typeof model === 'function' ? model() : model
|
|
50
65
|
}
|
|
51
66
|
|
|
67
|
+
function resolveAgentModelWithContext<TContext>(
|
|
68
|
+
model: AgentModelWithContext<TContext>,
|
|
69
|
+
context: TContext,
|
|
70
|
+
): LanguageModel {
|
|
71
|
+
return typeof model === 'function' ? (model as (ctx: TContext) => LanguageModel)(context) : model
|
|
72
|
+
}
|
|
73
|
+
|
|
52
74
|
function buildCurrentDateContext(now = nowDate()): string {
|
|
53
75
|
return [`Today is ${formatUtcPromptDate(now)}.`, 'Use this exact date for any recency reasoning.'].join(' ')
|
|
54
76
|
}
|
|
@@ -229,7 +251,7 @@ export function createDelegatedAgentTool(definition: DelegatedAgentDefinition):
|
|
|
229
251
|
description: definition.description,
|
|
230
252
|
inputSchema: z.object({ task: z.string().min(1) }),
|
|
231
253
|
execute: ({ task }: { task: string }, { abortSignal }) =>
|
|
232
|
-
|
|
254
|
+
definition.runPromise(
|
|
233
255
|
Effect.gen(function* () {
|
|
234
256
|
const agentTools = definition.tools
|
|
235
257
|
const createAgent = () =>
|
|
@@ -268,6 +290,7 @@ export function createDelegatedAgentTool(definition: DelegatedAgentDefinition):
|
|
|
268
290
|
}),
|
|
269
291
|
}
|
|
270
292
|
}),
|
|
293
|
+
abortSignal ? { signal: abortSignal } : undefined,
|
|
271
294
|
),
|
|
272
295
|
}),
|
|
273
296
|
} as const satisfies ToolDefinition<void>
|
|
@@ -286,13 +309,13 @@ export function createDelegatedAgentToolWithContext<TContext>(
|
|
|
286
309
|
description: definition.description,
|
|
287
310
|
inputSchema: z.object({ task: z.string().min(1) }),
|
|
288
311
|
execute: ({ task }: { task: string }, { abortSignal }) =>
|
|
289
|
-
|
|
312
|
+
definition.getRunPromise(context)(
|
|
290
313
|
Effect.gen(function* () {
|
|
291
314
|
const agentTools = definition.createTools(context)
|
|
292
315
|
const createAgent = () =>
|
|
293
316
|
new ToolLoopAgent({
|
|
294
317
|
id: definition.id,
|
|
295
|
-
model:
|
|
318
|
+
model: resolveAgentModelWithContext(definition.model, context),
|
|
296
319
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
297
320
|
...(definition.headers ? { headers: definition.headers } : {}),
|
|
298
321
|
instructions: buildDelegatedAgentInstructions(definition.instructions, agentTools),
|
|
@@ -304,7 +327,7 @@ export function createDelegatedAgentToolWithContext<TContext>(
|
|
|
304
327
|
})
|
|
305
328
|
const synthesize = (prompt: string, abortSignal?: AbortSignal) =>
|
|
306
329
|
generateText({
|
|
307
|
-
model:
|
|
330
|
+
model: resolveAgentModelWithContext(definition.model, context),
|
|
308
331
|
...(definition.providerOptions ? { providerOptions: definition.providerOptions } : {}),
|
|
309
332
|
...(definition.headers ? { headers: definition.headers } : {}),
|
|
310
333
|
system: `${definition.instructions.trim()}\n\nReturn a complete final markdown answer using only the provided research data. Do not call tools.`,
|
|
@@ -325,6 +348,7 @@ export function createDelegatedAgentToolWithContext<TContext>(
|
|
|
325
348
|
}),
|
|
326
349
|
}
|
|
327
350
|
}),
|
|
351
|
+
abortSignal ? { signal: abortSignal } : undefined,
|
|
328
352
|
),
|
|
329
353
|
}),
|
|
330
354
|
} as const satisfies ToolDefinition<TContext>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
5
5
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
6
6
|
import {
|
|
7
7
|
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
@@ -29,12 +29,13 @@ Set every item.relevance as a string; use empty string when no reason is needed.
|
|
|
29
29
|
</output>
|
|
30
30
|
</agent-instructions>`
|
|
31
31
|
|
|
32
|
-
export function
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
export function makeMemoryRerankerAgentFactory(models: AiGatewayModels) {
|
|
33
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
34
|
+
new ToolLoopAgent({
|
|
35
|
+
id: 'memory-reranker',
|
|
36
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
37
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
38
|
+
providerOptions: OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
39
|
+
...resolveHelperAgentOptions(options),
|
|
40
|
+
})
|
|
40
41
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
5
5
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
6
6
|
import {
|
|
7
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -49,12 +49,13 @@ Return only the schema fields with no extra formatting.
|
|
|
49
49
|
</format>
|
|
50
50
|
</agent-instructions>`
|
|
51
51
|
|
|
52
|
-
export function
|
|
53
|
-
return
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
export function makeOrgMemoryAgentFactory(models: AiGatewayModels) {
|
|
53
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
54
|
+
new ToolLoopAgent({
|
|
55
|
+
id: 'org-memory',
|
|
56
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
57
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
58
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
59
|
+
...resolveHelperAgentOptions(options),
|
|
60
|
+
})
|
|
60
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
5
5
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
6
6
|
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
7
7
|
import {
|
|
@@ -76,18 +76,16 @@ Return only the title text. No quotes, labels, JSON, markdown, or explanation.
|
|
|
76
76
|
</output>
|
|
77
77
|
</agent-instructions>`
|
|
78
78
|
|
|
79
|
-
export function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}),
|
|
92
|
-
})
|
|
79
|
+
export function makeRecentActivityTitleRefinerAgentFactory(models: AiGatewayModels, agentConfig: ResolvedAgentConfig) {
|
|
80
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
81
|
+
new ToolLoopAgent({
|
|
82
|
+
id: 'recent-activity-title-refiner',
|
|
83
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
84
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
85
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
86
|
+
...resolveHelperAgentOptions(options, {
|
|
87
|
+
instructions: buildRecentActivityTitleRefinerPrompt(agentConfig),
|
|
88
|
+
maxOutputTokens: RECENT_ACTIVITY_TITLE_MAX_TOKENS,
|
|
89
|
+
}),
|
|
90
|
+
})
|
|
93
91
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
5
5
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
6
6
|
import {
|
|
7
7
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -24,15 +24,16 @@ Synthesize an updated workspace profile summary and durable memory facts from co
|
|
|
24
24
|
</rules>
|
|
25
25
|
</agent-instructions>`
|
|
26
26
|
|
|
27
|
-
export function
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
export function makeRegularChatMemoryDigestAgentFactory(models: AiGatewayModels) {
|
|
28
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
29
|
+
new ToolLoopAgent({
|
|
30
|
+
id: 'regular-chat-memory-digest',
|
|
31
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
32
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
33
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
34
|
+
...resolveHelperAgentOptions(options, {
|
|
35
|
+
instructions: regularChatMemoryDigestPrompt,
|
|
36
|
+
maxOutputTokens: REGULAR_CHAT_MEMORY_DIGEST_MAX_TOKENS,
|
|
37
|
+
}),
|
|
38
|
+
})
|
|
38
39
|
}
|
|
@@ -2,7 +2,7 @@ import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
6
6
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
7
7
|
import {
|
|
8
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -42,15 +42,16 @@ export const SkillExtractionOutputSchema = z.object({ candidates: z.array(SkillC
|
|
|
42
42
|
|
|
43
43
|
export type SkillCandidate = z.infer<typeof SkillCandidateSchema>
|
|
44
44
|
|
|
45
|
-
export function
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
export function makeSkillExtractorAgentFactory(models: AiGatewayModels) {
|
|
46
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
47
|
+
new ToolLoopAgent({
|
|
48
|
+
id: 'skill-extractor',
|
|
49
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
50
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
51
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
52
|
+
...resolveHelperAgentOptions(options, {
|
|
53
|
+
instructions: skillExtractorPrompt,
|
|
54
|
+
maxOutputTokens: SKILL_EXTRACTOR_MAX_TOKENS,
|
|
55
|
+
}),
|
|
56
|
+
})
|
|
56
57
|
}
|
|
@@ -2,7 +2,7 @@ import type { CreateHelperToolLoopAgentOptions } from '@lota-sdk/shared'
|
|
|
2
2
|
import { ToolLoopAgent } from 'ai'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
6
6
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
7
7
|
import {
|
|
8
8
|
OPENROUTER_STRUCTURED_HELPER_MODEL_ID,
|
|
@@ -66,15 +66,16 @@ export const SkillManagerOutputSchema = z.object({
|
|
|
66
66
|
mergedSkill: MergedSkillSchema.optional(),
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
export function
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
export function makeSkillManagerAgentFactory(models: AiGatewayModels) {
|
|
70
|
+
return (options: CreateHelperToolLoopAgentOptions) =>
|
|
71
|
+
new ToolLoopAgent({
|
|
72
|
+
id: 'skill-manager',
|
|
73
|
+
model: models.chatModel(OPENROUTER_STRUCTURED_HELPER_MODEL_ID),
|
|
74
|
+
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
75
|
+
providerOptions: OPENROUTER_HIGH_REASONING_PROVIDER_OPTIONS,
|
|
76
|
+
...resolveHelperAgentOptions(options, {
|
|
77
|
+
instructions: skillManagerPrompt,
|
|
78
|
+
maxOutputTokens: SKILL_MANAGER_MAX_TOKENS,
|
|
79
|
+
}),
|
|
80
|
+
})
|
|
80
81
|
}
|
|
@@ -2,12 +2,12 @@ import { generateObject } from 'ai'
|
|
|
2
2
|
import { Effect } from 'effect'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import type { AiGatewayModels } from '../ai-gateway/ai-gateway'
|
|
6
6
|
import { buildAiGatewayDirectCacheHeaders } from '../ai-gateway/cache-headers'
|
|
7
7
|
import type { ResolvedAgentConfig } from '../config/agent-defaults'
|
|
8
8
|
import { chatLogger } from '../config/logger'
|
|
9
9
|
import type { ValidationError } from '../effect/errors'
|
|
10
|
-
import { AiGenerationError } from '../effect/errors'
|
|
10
|
+
import { ERROR_TAGS, AiGenerationError } from '../effect/errors'
|
|
11
11
|
import { zodParse } from '../effect/zod'
|
|
12
12
|
|
|
13
13
|
const TriageResultSchema = z.object({ agentId: z.string(), routingContext: z.string() })
|
|
@@ -170,6 +170,7 @@ function toRouterGenerationError(label: 'triage' | 'check', error: unknown): AiG
|
|
|
170
170
|
|
|
171
171
|
function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
172
172
|
agentConfig: ResolvedAgentConfig
|
|
173
|
+
aiGatewayModels: AiGatewayModels
|
|
173
174
|
schema: TSchema
|
|
174
175
|
system: string
|
|
175
176
|
prompt: string
|
|
@@ -180,7 +181,7 @@ function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
|
180
181
|
return Effect.tryPromise({
|
|
181
182
|
try: () =>
|
|
182
183
|
generateObject({
|
|
183
|
-
model:
|
|
184
|
+
model: params.aiGatewayModels.chatModel(modelId),
|
|
184
185
|
headers: buildAiGatewayDirectCacheHeaders('lota-sdk'),
|
|
185
186
|
providerOptions: { openai: { reasoningEffort: 'low' } },
|
|
186
187
|
schema: params.schema,
|
|
@@ -201,12 +202,12 @@ function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
|
201
202
|
),
|
|
202
203
|
Effect.flatMap(({ object }) => zodParse(params.schema, object)),
|
|
203
204
|
Effect.catchTags({
|
|
204
|
-
AiGenerationError: (error: AiGenerationError) =>
|
|
205
|
+
[ERROR_TAGS.AiGenerationError]: (error: AiGenerationError) =>
|
|
205
206
|
Effect.sync(() => {
|
|
206
207
|
chatLogger.error`[thread-router] ${params.label} failed: ${error.message}`
|
|
207
208
|
return null
|
|
208
209
|
}),
|
|
209
|
-
ValidationError: (error: ValidationError) =>
|
|
210
|
+
[ERROR_TAGS.ValidationError]: (error: ValidationError) =>
|
|
210
211
|
Effect.sync(() => {
|
|
211
212
|
chatLogger.error`[thread-router] ${params.label} failed: ${error.message}`
|
|
212
213
|
return null
|
|
@@ -217,6 +218,7 @@ function generateRouterObjectEffect<TSchema extends z.ZodTypeAny>(params: {
|
|
|
217
218
|
|
|
218
219
|
export function triageThreadMessage(params: {
|
|
219
220
|
agentConfig: ResolvedAgentConfig
|
|
221
|
+
aiGatewayModels: AiGatewayModels
|
|
220
222
|
threadTitle: string
|
|
221
223
|
members: readonly string[]
|
|
222
224
|
messageText: string
|
|
@@ -254,6 +256,7 @@ export function triageThreadMessage(params: {
|
|
|
254
256
|
|
|
255
257
|
const parsed = yield* generateRouterObjectEffect({
|
|
256
258
|
agentConfig: params.agentConfig,
|
|
259
|
+
aiGatewayModels: params.aiGatewayModels,
|
|
257
260
|
schema: TriageResultSchema,
|
|
258
261
|
system: TRIAGE_SYSTEM_PROMPT,
|
|
259
262
|
prompt,
|
|
@@ -280,6 +283,7 @@ export function triageThreadMessage(params: {
|
|
|
280
283
|
|
|
281
284
|
export function checkForNextAgent(params: {
|
|
282
285
|
agentConfig: ResolvedAgentConfig
|
|
286
|
+
aiGatewayModels: AiGatewayModels
|
|
283
287
|
threadTitle: string
|
|
284
288
|
members: readonly string[]
|
|
285
289
|
messageText: string
|
|
@@ -323,6 +327,7 @@ export function checkForNextAgent(params: {
|
|
|
323
327
|
|
|
324
328
|
const parsed = yield* generateRouterObjectEffect({
|
|
325
329
|
agentConfig: params.agentConfig,
|
|
330
|
+
aiGatewayModels: params.aiGatewayModels,
|
|
326
331
|
schema: CheckResultObjectSchema,
|
|
327
332
|
system: CHECK_SYSTEM_PROMPT,
|
|
328
333
|
prompt,
|