@lota-sdk/core 0.1.11 → 0.1.12
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 -87
- package/src/ai/index.ts +3 -0
- package/src/bifrost/index.ts +1 -0
- package/src/config/agent-defaults.ts +30 -7
- package/src/config/constants.ts +0 -9
- package/src/config/debug-logger.ts +43 -0
- package/src/config/index.ts +5 -0
- package/src/config/model-constants.ts +0 -3
- package/src/config/workstream-defaults.ts +4 -0
- package/src/db/cursor-pagination.ts +2 -2
- package/src/db/index.ts +10 -0
- package/src/db/memory.ts +9 -15
- package/src/document/index.ts +2 -0
- package/src/document/parsing.ts +0 -25
- package/src/embeddings/provider.ts +17 -8
- package/src/index.ts +15 -505
- package/src/queues/index.ts +10 -0
- package/src/redis/connection-accessor.ts +26 -0
- package/src/redis/connection.ts +1 -1
- package/src/redis/index.ts +9 -25
- package/src/redis/org-memory-lock.ts +1 -1
- package/src/redis/redis-lease-lock.ts +1 -1
- package/src/redis/stream-context.ts +12 -2
- package/src/runtime/agent-runtime-policy.ts +9 -5
- package/src/runtime/agent-stream-helpers.ts +6 -3
- package/src/runtime/agent-types.ts +1 -5
- package/src/runtime/approval-continuation.ts +9 -1
- package/src/runtime/chat-attachments.ts +1 -1
- package/src/runtime/chat-request-routing.ts +1 -1
- package/src/runtime/context-compaction-runtime.ts +2 -2
- package/src/runtime/context-compaction.ts +1 -1
- package/src/runtime/execution-plan.ts +1 -1
- package/src/runtime/index.ts +26 -0
- package/src/runtime/indexed-repositories-policy.ts +10 -10
- package/src/runtime/memory-pipeline.ts +0 -2
- package/src/runtime/runtime-config.ts +238 -0
- package/src/runtime/runtime-extensions.ts +3 -2
- package/src/runtime/runtime-worker-registry.ts +47 -0
- package/src/runtime/team-consultation-orchestrator.ts +9 -6
- package/src/runtime/team-consultation-prompts.ts +3 -2
- package/src/runtime/turn-lifecycle.ts +1 -1
- package/src/runtime/workstream-chat-helpers.ts +0 -54
- package/src/runtime/workstream-routing-policy.ts +3 -7
- package/src/runtime.ts +387 -0
- package/src/services/chat-attachments.service.ts +1 -1
- package/src/services/context-compaction.service.ts +1 -1
- package/src/services/execution-plan.service.ts +14 -16
- package/src/services/index.ts +14 -0
- package/src/services/learned-skill.service.ts +80 -37
- package/src/services/memory.service.ts +5 -4
- package/src/services/mutating-approval.service.ts +1 -1
- package/src/services/organization-member.service.ts +1 -1
- package/src/services/organization.service.ts +1 -1
- package/src/services/plan-approval.service.ts +2 -2
- package/src/services/plan-artifact.service.ts +2 -3
- package/src/services/plan-builder.service.ts +1 -1
- package/src/services/plan-checkpoint.service.ts +2 -2
- package/src/services/plan-compiler.service.ts +2 -2
- package/src/services/plan-executor.service.ts +10 -9
- package/src/services/plan-run.service.ts +2 -2
- package/src/services/plan-validator.service.ts +4 -4
- package/src/services/recent-activity-title.service.ts +1 -1
- package/src/services/recent-activity.service.ts +14 -16
- package/src/services/user.service.ts +2 -2
- package/src/services/workstream-message.service.ts +2 -3
- package/src/services/workstream-title.service.ts +1 -1
- package/src/services/workstream-turn-preparation.ts +105 -50
- package/src/services/workstream-turn.ts +14 -1
- package/src/services/workstream.service.ts +9 -9
- package/src/storage/attachment-parser.ts +1 -1
- package/src/storage/attachment-storage.service.ts +11 -10
- package/src/storage/generated-document-storage.service.ts +7 -6
- package/src/storage/index.ts +10 -0
- package/src/system-agents/delegated-agent-factory.ts +78 -29
- package/src/system-agents/index.ts +4 -0
- package/src/system-agents/recent-activity-title-refiner.agent.ts +38 -3
- 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 +2 -4
- package/src/tools/execution-plan.tool.ts +2 -2
- package/src/tools/firecrawl-client.ts +2 -2
- package/src/tools/index.ts +12 -0
- package/src/tools/research-topic.tool.ts +1 -1
- package/src/tools/team-think.tool.ts +1 -1
- package/src/tools/user-questions.tool.ts +2 -2
- package/src/utils/index.ts +6 -0
- package/src/workers/bootstrap.ts +8 -16
- package/src/workers/index.ts +7 -0
- package/src/workers/regular-chat-memory-digest.runner.ts +1 -1
- package/src/workers/skill-extraction.runner.ts +1 -1
- package/src/workers/utils/{repo-indexer-chunker.ts → file-section-chunker.ts} +23 -52
- package/src/workers/utils/repo-structure-extractor.ts +2 -5
- package/src/workers/utils/repomix-file-sections.ts +42 -0
- package/src/config/env-shapes.ts +0 -121
- package/src/runtime/agent-contract.ts +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lota-sdk/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -13,91 +13,6 @@
|
|
|
13
13
|
"bun": "./src/index.ts",
|
|
14
14
|
"import": "./src/index.ts",
|
|
15
15
|
"types": "./src/index.ts"
|
|
16
|
-
},
|
|
17
|
-
"./ai/*": {
|
|
18
|
-
"bun": "./src/ai/*.ts",
|
|
19
|
-
"import": "./src/ai/*.ts",
|
|
20
|
-
"types": "./src/ai/*.ts"
|
|
21
|
-
},
|
|
22
|
-
"./bifrost": {
|
|
23
|
-
"bun": "./src/bifrost/bifrost.ts",
|
|
24
|
-
"import": "./src/bifrost/bifrost.ts",
|
|
25
|
-
"types": "./src/bifrost/bifrost.ts"
|
|
26
|
-
},
|
|
27
|
-
"./bifrost/*": {
|
|
28
|
-
"bun": "./src/bifrost/*.ts",
|
|
29
|
-
"import": "./src/bifrost/*.ts",
|
|
30
|
-
"types": "./src/bifrost/*.ts"
|
|
31
|
-
},
|
|
32
|
-
"./runtime/*": {
|
|
33
|
-
"bun": "./src/runtime/*.ts",
|
|
34
|
-
"import": "./src/runtime/*.ts",
|
|
35
|
-
"types": "./src/runtime/*.ts"
|
|
36
|
-
},
|
|
37
|
-
"./tools/*": {
|
|
38
|
-
"bun": "./src/tools/*.ts",
|
|
39
|
-
"import": "./src/tools/*.ts",
|
|
40
|
-
"types": "./src/tools/*.ts"
|
|
41
|
-
},
|
|
42
|
-
"./storage/*": {
|
|
43
|
-
"bun": "./src/storage/*.ts",
|
|
44
|
-
"import": "./src/storage/*.ts",
|
|
45
|
-
"types": "./src/storage/*.ts"
|
|
46
|
-
},
|
|
47
|
-
"./document/*": {
|
|
48
|
-
"bun": "./src/document/*.ts",
|
|
49
|
-
"import": "./src/document/*.ts",
|
|
50
|
-
"types": "./src/document/*.ts"
|
|
51
|
-
},
|
|
52
|
-
"./system-agents/*": {
|
|
53
|
-
"bun": "./src/system-agents/*.ts",
|
|
54
|
-
"import": "./src/system-agents/*.ts",
|
|
55
|
-
"types": "./src/system-agents/*.ts"
|
|
56
|
-
},
|
|
57
|
-
"./db/*": {
|
|
58
|
-
"bun": "./src/db/*.ts",
|
|
59
|
-
"import": "./src/db/*.ts",
|
|
60
|
-
"types": "./src/db/*.ts"
|
|
61
|
-
},
|
|
62
|
-
"./redis": {
|
|
63
|
-
"bun": "./src/redis/index.ts",
|
|
64
|
-
"import": "./src/redis/index.ts",
|
|
65
|
-
"types": "./src/redis/index.ts"
|
|
66
|
-
},
|
|
67
|
-
"./redis/*": {
|
|
68
|
-
"bun": "./src/redis/*.ts",
|
|
69
|
-
"import": "./src/redis/*.ts",
|
|
70
|
-
"types": "./src/redis/*.ts"
|
|
71
|
-
},
|
|
72
|
-
"./services/*": {
|
|
73
|
-
"bun": "./src/services/*.ts",
|
|
74
|
-
"import": "./src/services/*.ts",
|
|
75
|
-
"types": "./src/services/*.ts"
|
|
76
|
-
},
|
|
77
|
-
"./config/*": {
|
|
78
|
-
"bun": "./src/config/*.ts",
|
|
79
|
-
"import": "./src/config/*.ts",
|
|
80
|
-
"types": "./src/config/*.ts"
|
|
81
|
-
},
|
|
82
|
-
"./utils/*": {
|
|
83
|
-
"bun": "./src/utils/*.ts",
|
|
84
|
-
"import": "./src/utils/*.ts",
|
|
85
|
-
"types": "./src/utils/*.ts"
|
|
86
|
-
},
|
|
87
|
-
"./queues/*": {
|
|
88
|
-
"bun": "./src/queues/*.ts",
|
|
89
|
-
"import": "./src/queues/*.ts",
|
|
90
|
-
"types": "./src/queues/*.ts"
|
|
91
|
-
},
|
|
92
|
-
"./workers/*": {
|
|
93
|
-
"bun": "./src/workers/*.ts",
|
|
94
|
-
"import": "./src/workers/*.ts",
|
|
95
|
-
"types": "./src/workers/*.ts"
|
|
96
|
-
},
|
|
97
|
-
"./embeddings": {
|
|
98
|
-
"bun": "./src/embeddings/provider.ts",
|
|
99
|
-
"import": "./src/embeddings/provider.ts",
|
|
100
|
-
"types": "./src/embeddings/provider.ts"
|
|
101
16
|
}
|
|
102
17
|
},
|
|
103
18
|
"scripts": {
|
|
@@ -115,7 +30,7 @@
|
|
|
115
30
|
"@ai-sdk/devtools": "^0.0.15",
|
|
116
31
|
"@ai-sdk/openai": "^3.0.41",
|
|
117
32
|
"@logtape/logtape": "^2.0.4",
|
|
118
|
-
"@lota-sdk/shared": "0.1.
|
|
33
|
+
"@lota-sdk/shared": "0.1.11",
|
|
119
34
|
"@mendable/firecrawl-js": "^4.16.0",
|
|
120
35
|
"@surrealdb/node": "^3.0.3",
|
|
121
36
|
"ai": "^6.0.116",
|
package/src/ai/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './bifrost'
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
type LotaAgentFactoryRegistry = Record<string, (...args: unknown[]) => unknown>
|
|
2
2
|
|
|
3
|
+
function defaultBuildAgentTools(): Record<string, never> {
|
|
4
|
+
return {}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function defaultGetAgentRuntimeConfig(): Record<string, never> {
|
|
8
|
+
return {}
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
// Agent configuration — these are defaults that consumers override via createLotaRuntime config
|
|
4
12
|
export let agentDisplayNames: Record<string, string> = {}
|
|
5
13
|
export let agentShortDisplayNames: Record<string, string> = {}
|
|
6
14
|
export let agentRoster: readonly string[] = []
|
|
15
|
+
export let leadAgentId = ''
|
|
7
16
|
export let teamConsultParticipants: readonly string[] = []
|
|
8
17
|
|
|
9
18
|
export interface CoreWorkstreamProfile {
|
|
@@ -22,12 +31,18 @@ export let getCoreWorkstreamProfile: (coreType: string) => CoreWorkstreamProfile
|
|
|
22
31
|
|
|
23
32
|
export function configureAgents(config: {
|
|
24
33
|
roster: readonly string[]
|
|
34
|
+
leadAgentId: string
|
|
25
35
|
displayNames: Record<string, string>
|
|
26
36
|
shortDisplayNames?: Record<string, string>
|
|
27
37
|
teamConsultParticipants: readonly string[]
|
|
28
38
|
getCoreWorkstreamProfile?: (coreType: string) => CoreWorkstreamProfile
|
|
29
39
|
}): void {
|
|
40
|
+
if (!config.roster.includes(config.leadAgentId)) {
|
|
41
|
+
throw new Error(`Lead agent "${config.leadAgentId}" must be present in the configured roster.`)
|
|
42
|
+
}
|
|
43
|
+
|
|
30
44
|
agentRoster = config.roster
|
|
45
|
+
leadAgentId = config.leadAgentId
|
|
31
46
|
agentDisplayNames = config.displayNames
|
|
32
47
|
agentShortDisplayNames = config.shortDisplayNames ?? {}
|
|
33
48
|
teamConsultParticipants = config.teamConsultParticipants
|
|
@@ -40,6 +55,14 @@ export function isAgentName(value: unknown): boolean {
|
|
|
40
55
|
return typeof value === 'string' && new Set(agentRoster).has(value)
|
|
41
56
|
}
|
|
42
57
|
|
|
58
|
+
export function getLeadAgentId(): string {
|
|
59
|
+
return leadAgentId
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getLeadAgentDisplayName(): string {
|
|
63
|
+
return agentDisplayNames[leadAgentId] ?? leadAgentId
|
|
64
|
+
}
|
|
65
|
+
|
|
43
66
|
export function resolveAgentNameAlias(value: unknown): string | undefined {
|
|
44
67
|
if (typeof value !== 'string') return undefined
|
|
45
68
|
const lowered = value.trim().toLowerCase()
|
|
@@ -56,20 +79,20 @@ export function resolveAgentNameAlias(value: unknown): string | undefined {
|
|
|
56
79
|
|
|
57
80
|
export let createAgent: LotaAgentFactoryRegistry = {}
|
|
58
81
|
|
|
59
|
-
export let buildAgentTools: (...args: unknown[]) => unknown =
|
|
60
|
-
export let getAgentRuntimeConfig: (...args: unknown[]) => unknown =
|
|
82
|
+
export let buildAgentTools: (...args: unknown[]) => unknown = defaultBuildAgentTools
|
|
83
|
+
export let getAgentRuntimeConfig: (...args: unknown[]) => unknown = defaultGetAgentRuntimeConfig
|
|
61
84
|
export let pluginRuntime: unknown = undefined
|
|
62
85
|
|
|
63
86
|
export function configureAgentFactory(config: {
|
|
64
|
-
createAgent
|
|
87
|
+
createAgent?: LotaAgentFactoryRegistry
|
|
65
88
|
buildAgentTools?: (...args: unknown[]) => unknown
|
|
66
89
|
getAgentRuntimeConfig?: (...args: unknown[]) => unknown
|
|
67
90
|
pluginRuntime?: unknown
|
|
68
91
|
}): void {
|
|
69
|
-
createAgent = config.createAgent
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
92
|
+
createAgent = config.createAgent ?? {}
|
|
93
|
+
buildAgentTools = config.buildAgentTools ?? defaultBuildAgentTools
|
|
94
|
+
getAgentRuntimeConfig = config.getAgentRuntimeConfig ?? defaultGetAgentRuntimeConfig
|
|
95
|
+
pluginRuntime = config.pluginRuntime
|
|
73
96
|
}
|
|
74
97
|
|
|
75
98
|
const AGENT_MENTION_REGEX = /(^|[^\w])@([a-z][a-z0-9_-]*)\b/gi
|
package/src/config/constants.ts
CHANGED
|
@@ -22,12 +22,3 @@ export const MEMORY = {
|
|
|
22
22
|
export function validateKnnLimit(limit: unknown): number {
|
|
23
23
|
return z.number().int().positive().max(MEMORY.MAX_KNN_LIMIT).parse(limit)
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Creates a KNN query string with validated limit
|
|
28
|
-
* Example: createKnnQuery(10) returns "<|10|>"
|
|
29
|
-
*/
|
|
30
|
-
export function createKnnQuery(limit: unknown): string {
|
|
31
|
-
const validatedLimit = validateKnnLimit(limit)
|
|
32
|
-
return `<|${validatedLimit}|>`
|
|
33
|
-
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { chatLogger } from './logger'
|
|
2
|
+
|
|
3
|
+
const isDebug = () => process.env.LOG_LEVEL === 'debug' || process.env.LOTA_DEBUG === '1'
|
|
4
|
+
|
|
5
|
+
interface DebugTimer {
|
|
6
|
+
step(name: string): void
|
|
7
|
+
elapsed(): number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const NOOP_TIMER: DebugTimer = { step() {}, elapsed: () => 0 }
|
|
11
|
+
|
|
12
|
+
function createTimer(label: string): DebugTimer {
|
|
13
|
+
const start = performance.now()
|
|
14
|
+
let lastStep = start
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
step(name: string) {
|
|
18
|
+
const now = performance.now()
|
|
19
|
+
const stepMs = now - lastStep
|
|
20
|
+
const totalMs = now - start
|
|
21
|
+
chatLogger.debug`[ttft:${label}] ${name}: ${stepMs.toFixed(1)}ms (elapsed: ${totalMs.toFixed(1)}ms)`
|
|
22
|
+
lastStep = now
|
|
23
|
+
},
|
|
24
|
+
elapsed() {
|
|
25
|
+
return performance.now() - start
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const lotaDebugLogger = {
|
|
31
|
+
get enabled() {
|
|
32
|
+
return isDebug()
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
timer(label: string): DebugTimer {
|
|
36
|
+
return isDebug() ? createTimer(label) : NOOP_TIMER
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
step(name: string) {
|
|
40
|
+
if (!isDebug()) return
|
|
41
|
+
chatLogger.debug`[ttft] ${name}`
|
|
42
|
+
},
|
|
43
|
+
}
|
|
@@ -4,9 +4,6 @@ export const OPENROUTER_TEAM_AGENT_MODEL_ID = 'openrouter/google/gemini-3.1-pro-
|
|
|
4
4
|
export const OPENROUTER_STRUCTURED_HELPER_MODEL_ID = 'openrouter/google/gemini-3-flash-preview:exacto' as const
|
|
5
5
|
export const OPENROUTER_DELEGATED_REASONING_MODEL_ID = 'openrouter/google/gemini-3-flash-preview:exacto' as const
|
|
6
6
|
export const OPENROUTER_WEB_RESEARCH_MODEL_ID = 'openrouter/stepfun/step-3.5-flash' as const
|
|
7
|
-
export const OPENROUTER_ARTIFACT_GENERATOR_MODEL_ID = 'openrouter/qwen/qwen3.5-flash-02-23' as const
|
|
8
|
-
export const OPENROUTER_REPO_INDEXER_MODEL_ID = 'openrouter/qwen/qwen3.5-flash-02-23:nitro' as const
|
|
9
|
-
export const OPENROUTER_CODE_ANALYSIS_MODEL_ID = 'openrouter/xiaomi/mimo-v2-flash' as const
|
|
10
7
|
export const OPENROUTER_FAST_REASONING_MODEL_ID = 'openrouter/openai/gpt-oss-120b:nitro' as const
|
|
11
8
|
export const OPENROUTER_STRUCTURED_REASONING_MODEL_ID = 'openrouter/openai/gpt-oss-120b:exacto' as const
|
|
12
9
|
|
|
@@ -66,3 +66,7 @@ export function configureWorkstreams(params: { agentRoster: readonly string[]; c
|
|
|
66
66
|
export function getWorkstreamBootstrapConfig(): ResolvedWorkstreamBootstrapConfig {
|
|
67
67
|
return resolvedWorkstreamBootstrapConfig
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
export function resolveOnboardingOwnerAgentId(defaultLeadAgentId: string): string {
|
|
71
|
+
return resolvedWorkstreamBootstrapConfig.onboardingWelcome?.directAgentId ?? defaultLeadAgentId
|
|
72
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { toTimestamp } from '@lota-sdk/shared
|
|
2
|
-
import type { ChatMessage } from '@lota-sdk/shared
|
|
1
|
+
import { toTimestamp } from '@lota-sdk/shared'
|
|
2
|
+
import type { ChatMessage } from '@lota-sdk/shared'
|
|
3
3
|
import type { BoundQuery, RecordId } from 'surrealdb'
|
|
4
4
|
import { z } from 'zod'
|
|
5
5
|
|
package/src/db/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './cursor-pagination'
|
|
2
|
+
export * from './memory'
|
|
3
|
+
export * from './memory-store'
|
|
4
|
+
export * from './memory-store.helpers'
|
|
5
|
+
export * from './memory-types'
|
|
6
|
+
export * from './record-id'
|
|
7
|
+
export * from './sdk-database'
|
|
8
|
+
export * from './service'
|
|
9
|
+
export * from './startup'
|
|
10
|
+
export * from './tables'
|
package/src/db/memory.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { env } from '../config/env-shapes'
|
|
2
1
|
import { aiLogger } from '../config/logger'
|
|
3
2
|
import type { CreateHelperAgentFn } from '../runtime/helper-model'
|
|
4
3
|
import { createHelperModelRuntime } from '../runtime/helper-model'
|
|
@@ -12,6 +11,7 @@ import {
|
|
|
12
11
|
import { getFactRetrievalMessages } from '../runtime/memory-prompts-fact'
|
|
13
12
|
import { parseMessages } from '../runtime/memory-prompts-parse'
|
|
14
13
|
import { getClassifyMemoryDeltaPrompt } from '../runtime/memory-prompts-update'
|
|
14
|
+
import { getRuntimeConfig } from '../runtime/runtime-config'
|
|
15
15
|
import type { SurrealMemoryStore } from './memory-store'
|
|
16
16
|
import { getDefaultMemoryStore } from './memory-store'
|
|
17
17
|
import { hashContent, isUniqueIndexConflict } from './memory-store.helpers'
|
|
@@ -91,23 +91,15 @@ export class Memory {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
async search(query: string, options: SearchOptions): Promise<string> {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
options.scopeId,
|
|
97
|
-
options.limit ?? env.MEMORY_SEARCH_K,
|
|
98
|
-
options.memoryType,
|
|
99
|
-
)
|
|
94
|
+
const limit = options.limit ?? getRuntimeConfig().memory.searchK
|
|
95
|
+
const results = await this.store.search(query, options.scopeId, limit, options.memoryType)
|
|
100
96
|
|
|
101
97
|
return formatResults(results)
|
|
102
98
|
}
|
|
103
99
|
|
|
104
100
|
async hybridSearch(query: string, options: SearchOptions): Promise<string> {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
options.scopeId,
|
|
108
|
-
options.limit ?? env.MEMORY_SEARCH_K,
|
|
109
|
-
options.memoryType,
|
|
110
|
-
)
|
|
101
|
+
const limit = options.limit ?? getRuntimeConfig().memory.searchK
|
|
102
|
+
const results = await this.store.hybridSearch(query, options.scopeId, limit, options.memoryType)
|
|
111
103
|
|
|
112
104
|
return formatResults(results)
|
|
113
105
|
}
|
|
@@ -116,9 +108,10 @@ export class Memory {
|
|
|
116
108
|
query: string,
|
|
117
109
|
options: SearchOptions & { weights?: [number, number]; normalization?: 'minmax' | 'zscore' },
|
|
118
110
|
): Promise<string> {
|
|
111
|
+
const limit = options.limit ?? getRuntimeConfig().memory.searchK
|
|
119
112
|
const results = await this.store.hybridSearchWeighted(query, {
|
|
120
113
|
scopeId: options.scopeId,
|
|
121
|
-
limit
|
|
114
|
+
limit,
|
|
122
115
|
memoryType: options.memoryType,
|
|
123
116
|
weights: options.weights,
|
|
124
117
|
normalization: options.normalization,
|
|
@@ -128,9 +121,10 @@ export class Memory {
|
|
|
128
121
|
}
|
|
129
122
|
|
|
130
123
|
async searchCandidates(query: string, options: WeightedSearchOptions): Promise<MemorySearchResult[]> {
|
|
124
|
+
const limit = options.limit ?? getRuntimeConfig().memory.searchK
|
|
131
125
|
const results = await this.store.hybridSearchWeighted(query, {
|
|
132
126
|
scopeId: options.scopeId,
|
|
133
|
-
limit
|
|
127
|
+
limit,
|
|
134
128
|
memoryType: options.memoryType,
|
|
135
129
|
weights: options.weights,
|
|
136
130
|
normalization: options.normalization,
|
package/src/document/parsing.ts
CHANGED
|
@@ -13,28 +13,3 @@ export function normalizeKey(value: string): string {
|
|
|
13
13
|
.replace(/\s+/g, '-')
|
|
14
14
|
.slice(0, 120)
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
export function makeMemoryKey(kind: string, rawKey: string): string {
|
|
18
|
-
const normalized = normalizeKey(rawKey)
|
|
19
|
-
return normalized ? `${kind}:${normalized}` : `${kind}:item`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function truncateForModel(value: string, maxChars: number): string {
|
|
23
|
-
if (value.length <= maxChars) return value
|
|
24
|
-
return `${value.slice(0, maxChars)}\n\n[...truncated due to size...]`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function dedupeStrings(items: string[], limit: number): string[] {
|
|
28
|
-
const out: string[] = []
|
|
29
|
-
const seen = new Set<string>()
|
|
30
|
-
for (const raw of items) {
|
|
31
|
-
const value = normalizeWhitespace(raw)
|
|
32
|
-
if (!value) continue
|
|
33
|
-
const key = value.toLowerCase()
|
|
34
|
-
if (seen.has(key)) continue
|
|
35
|
-
seen.add(key)
|
|
36
|
-
out.push(value)
|
|
37
|
-
if (out.length >= limit) break
|
|
38
|
-
}
|
|
39
|
-
return out
|
|
40
|
-
}
|
|
@@ -2,7 +2,7 @@ import { embed, embedMany } from 'ai'
|
|
|
2
2
|
|
|
3
3
|
import { getEmbeddingCache } from '../ai/embedding-cache'
|
|
4
4
|
import { bifrostEmbeddingModel } from '../bifrost/bifrost'
|
|
5
|
-
import {
|
|
5
|
+
import { getRuntimeConfig } from '../runtime/runtime-config'
|
|
6
6
|
|
|
7
7
|
const SUPPORTED_EMBEDDING_PREFIXES = ['openai/', 'openrouter/'] as const
|
|
8
8
|
|
|
@@ -41,19 +41,28 @@ export class ProviderEmbeddings {
|
|
|
41
41
|
private readonly embedFn: typeof embed
|
|
42
42
|
private readonly embedManyFn: typeof embedMany
|
|
43
43
|
private readonly getCache: () => SharedEmbeddingCache | null
|
|
44
|
-
private readonly
|
|
44
|
+
private readonly configuredModelId?: string
|
|
45
|
+
private resolvedModelId: string | null = null
|
|
45
46
|
private _model: ReturnType<typeof resolveEmbeddingModel> | null = null
|
|
46
47
|
|
|
47
48
|
constructor(options: ProviderEmbeddingsOptions = {}) {
|
|
48
49
|
this.embedFn = options.embedFn ?? embed
|
|
49
50
|
this.embedManyFn = options.embedManyFn ?? embedMany
|
|
50
51
|
this.getCache = options.getCache ?? getEmbeddingCache
|
|
51
|
-
this.
|
|
52
|
+
this.configuredModelId = options.modelId
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private getModelId(): string {
|
|
56
|
+
if (!this.resolvedModelId) {
|
|
57
|
+
this.resolvedModelId = this.configuredModelId ?? getRuntimeConfig().aiGateway.embeddingModel
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return this.resolvedModelId
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
private getModel() {
|
|
55
64
|
if (!this._model) {
|
|
56
|
-
this._model = resolveEmbeddingModel(this.
|
|
65
|
+
this._model = resolveEmbeddingModel(this.getModelId())
|
|
57
66
|
}
|
|
58
67
|
return this._model
|
|
59
68
|
}
|
|
@@ -62,7 +71,7 @@ export class ProviderEmbeddings {
|
|
|
62
71
|
const redisCache = this.getCache()
|
|
63
72
|
if (!redisCache) return null
|
|
64
73
|
|
|
65
|
-
return await redisCache.get(this.
|
|
74
|
+
return await redisCache.get(this.getModelId(), text)
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
async embedQuery(text: string): Promise<number[]> {
|
|
@@ -77,7 +86,7 @@ export class ProviderEmbeddings {
|
|
|
77
86
|
|
|
78
87
|
const redisCache = this.getCache()
|
|
79
88
|
if (redisCache) {
|
|
80
|
-
void redisCache.set(this.
|
|
89
|
+
void redisCache.set(this.getModelId(), input, embedding)
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
return embedding
|
|
@@ -102,7 +111,7 @@ export class ProviderEmbeddings {
|
|
|
102
111
|
const redisCache = this.getCache()
|
|
103
112
|
if (redisCache && missingTexts.length > 0) {
|
|
104
113
|
const redisResults = await Promise.all(
|
|
105
|
-
missingTexts.map(async (text) => ({ text, embedding: await redisCache.get(this.
|
|
114
|
+
missingTexts.map(async (text) => ({ text, embedding: await redisCache.get(this.getModelId(), text) })),
|
|
106
115
|
)
|
|
107
116
|
|
|
108
117
|
missingTexts = []
|
|
@@ -123,7 +132,7 @@ export class ProviderEmbeddings {
|
|
|
123
132
|
const embedding = normalizeEmbedding(result.embeddings[index] ?? [])
|
|
124
133
|
embeddingsByText.set(text, embedding)
|
|
125
134
|
if (redisCache) {
|
|
126
|
-
void redisCache.set(this.
|
|
135
|
+
void redisCache.set(this.getModelId(), text, embedding)
|
|
127
136
|
}
|
|
128
137
|
})
|
|
129
138
|
}
|