@lota-sdk/core 0.1.11 → 0.1.13
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
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import { recordIdStringSchema } from '@lota-sdk/shared
|
|
1
|
+
import { recordIdStringSchema } from '@lota-sdk/shared'
|
|
2
2
|
import { BoundQuery } from 'surrealdb'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
5
5
|
import { renderLearnedSkillInstructions } from '../ai/definitions'
|
|
6
|
+
import { lotaDebugLogger } from '../config/debug-logger'
|
|
6
7
|
import { serverLogger } from '../config/logger'
|
|
7
8
|
import { ensureRecordId } from '../db/record-id'
|
|
8
9
|
import { databaseService } from '../db/service'
|
|
9
10
|
import { TABLES } from '../db/tables'
|
|
10
11
|
import { getDefaultEmbeddings } from '../embeddings/provider'
|
|
12
|
+
import { getRedisConnection } from '../redis'
|
|
11
13
|
|
|
12
14
|
const embeddings = getDefaultEmbeddings()
|
|
13
15
|
|
|
14
16
|
const PROMOTION_MIN_USES = 5
|
|
15
17
|
const PROMOTION_MIN_SUCCESS_RATE = 0.6
|
|
16
18
|
|
|
19
|
+
const SKILL_EXISTS_TTL_SECONDS = 120
|
|
20
|
+
const SKILL_EXISTS_KEY_PREFIX = 'skill-exists'
|
|
21
|
+
|
|
22
|
+
function skillExistsKey(orgId: string, agentId: string): string {
|
|
23
|
+
return `${SKILL_EXISTS_KEY_PREFIX}:${orgId}:${agentId}`
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
const LearnedSkillRowSchema = z.object({
|
|
18
27
|
id: recordIdStringSchema,
|
|
19
28
|
name: z.string(),
|
|
@@ -51,7 +60,7 @@ const SearchResultRowSchema = z.object({
|
|
|
51
60
|
|
|
52
61
|
type SearchResultRow = z.infer<typeof SearchResultRowSchema>
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
interface CreateLearnedSkillInput {
|
|
55
64
|
name: string
|
|
56
65
|
description: string
|
|
57
66
|
instructions: string
|
|
@@ -66,7 +75,7 @@ export interface CreateLearnedSkillInput {
|
|
|
66
75
|
hash: string
|
|
67
76
|
}
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
interface UpdateLearnedSkillInput {
|
|
70
79
|
name?: string
|
|
71
80
|
description?: string
|
|
72
81
|
instructions?: string
|
|
@@ -80,7 +89,7 @@ export interface UpdateLearnedSkillInput {
|
|
|
80
89
|
supersedes?: string
|
|
81
90
|
}
|
|
82
91
|
|
|
83
|
-
|
|
92
|
+
interface RetrieveForTurnParams {
|
|
84
93
|
orgId: string
|
|
85
94
|
agentId: string
|
|
86
95
|
query: string
|
|
@@ -107,7 +116,9 @@ class LearnedSkillService {
|
|
|
107
116
|
hash: input.hash,
|
|
108
117
|
}
|
|
109
118
|
|
|
110
|
-
|
|
119
|
+
const result = await databaseService.create(TABLES.LEARNED_SKILL, data, LearnedSkillRowSchema)
|
|
120
|
+
await this.invalidateSkillExistsCache(input.organizationId, input.agentId)
|
|
121
|
+
return result
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
async update(skillId: string, input: UpdateLearnedSkillInput): Promise<LearnedSkillRow> {
|
|
@@ -133,12 +144,16 @@ class LearnedSkillService {
|
|
|
133
144
|
|
|
134
145
|
async archive(skillId: string): Promise<void> {
|
|
135
146
|
const ref = ensureRecordId(skillId, TABLES.LEARNED_SKILL)
|
|
147
|
+
const skill = await this.getById(skillId)
|
|
136
148
|
await databaseService.update(
|
|
137
149
|
TABLES.LEARNED_SKILL,
|
|
138
150
|
ref,
|
|
139
151
|
{ status: 'archived', archivedAt: new Date().toISOString(), updatedAt: new Date().toISOString() },
|
|
140
152
|
LearnedSkillRowSchema,
|
|
141
153
|
)
|
|
154
|
+
if (skill) {
|
|
155
|
+
await this.invalidateSkillExistsCache(String(skill.organizationId), skill.agentId ?? null)
|
|
156
|
+
}
|
|
142
157
|
}
|
|
143
158
|
|
|
144
159
|
async getById(skillId: string): Promise<LearnedSkillRow | null> {
|
|
@@ -149,27 +164,60 @@ class LearnedSkillService {
|
|
|
149
164
|
)
|
|
150
165
|
}
|
|
151
166
|
|
|
167
|
+
private async hasSkillsForAgent(orgId: string, agentId: string): Promise<boolean> {
|
|
168
|
+
const redis = getRedisConnection()
|
|
169
|
+
const key = skillExistsKey(orgId, agentId)
|
|
170
|
+
|
|
171
|
+
const cached = await redis.get(key)
|
|
172
|
+
if (cached !== null) return cached === '1'
|
|
173
|
+
|
|
174
|
+
const orgRef = ensureRecordId(orgId, TABLES.ORGANIZATION)
|
|
175
|
+
const rows = await databaseService.query<{ id: unknown }>(
|
|
176
|
+
new BoundQuery(
|
|
177
|
+
`SELECT id FROM ${TABLES.LEARNED_SKILL}
|
|
178
|
+
WHERE organizationId = $orgRef
|
|
179
|
+
AND status IN ['learned', 'verified', 'promoted']
|
|
180
|
+
AND archivedAt IS NONE
|
|
181
|
+
AND (agentId IS NONE OR agentId = $agentId)
|
|
182
|
+
LIMIT 1`,
|
|
183
|
+
{ orgRef, agentId },
|
|
184
|
+
),
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
const exists = rows.length > 0
|
|
188
|
+
await redis.set(key, exists ? '1' : '0', 'EX', SKILL_EXISTS_TTL_SECONDS)
|
|
189
|
+
return exists
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private async invalidateSkillExistsCache(orgId: string, agentId: string | null): Promise<void> {
|
|
193
|
+
const redis = getRedisConnection()
|
|
194
|
+
const pattern = `${SKILL_EXISTS_KEY_PREFIX}:${orgId}:*`
|
|
195
|
+
const keys = await redis.keys(pattern)
|
|
196
|
+
if (keys.length > 0) {
|
|
197
|
+
await redis.del(...keys)
|
|
198
|
+
}
|
|
199
|
+
// Also set the specific key if we know a skill was just created
|
|
200
|
+
if (agentId) {
|
|
201
|
+
await redis.set(skillExistsKey(orgId, agentId), '1', 'EX', SKILL_EXISTS_TTL_SECONDS)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
152
205
|
async searchForTurn(params: RetrieveForTurnParams): Promise<SearchResultRow[]> {
|
|
153
|
-
const
|
|
206
|
+
const timer = lotaDebugLogger.timer('learned-skills')
|
|
207
|
+
|
|
208
|
+
const hasSkills = await this.hasSkillsForAgent(params.orgId, params.agentId)
|
|
209
|
+
if (!hasSkills) {
|
|
210
|
+
lotaDebugLogger.step('learned-skills: skipped — no skills for org+agent')
|
|
211
|
+
return []
|
|
212
|
+
}
|
|
213
|
+
timer.step('has-skills-check')
|
|
214
|
+
|
|
154
215
|
const queryEmbedding = await embeddings.embedQuery(params.query)
|
|
216
|
+
timer.step('embed-query')
|
|
155
217
|
if (queryEmbedding.length === 0) return []
|
|
156
218
|
|
|
157
|
-
const
|
|
219
|
+
const orgRef = ensureRecordId(params.orgId, TABLES.ORGANIZATION)
|
|
158
220
|
const sql = `
|
|
159
|
-
LET $candidateRows = (
|
|
160
|
-
SELECT
|
|
161
|
-
id,
|
|
162
|
-
vector::distance::knn() AS distance
|
|
163
|
-
FROM ${TABLES.LEARNED_SKILL}
|
|
164
|
-
WHERE organizationId = $organizationId
|
|
165
|
-
AND status IN ['learned', 'verified', 'promoted']
|
|
166
|
-
AND archivedAt IS NONE
|
|
167
|
-
AND confidence >= $minConfidence
|
|
168
|
-
AND (agentId IS NONE OR agentId = $agentId)
|
|
169
|
-
AND embedding <|${candidateLimit}|> $embedding
|
|
170
|
-
ORDER BY distance ASC
|
|
171
|
-
);
|
|
172
|
-
|
|
173
221
|
SELECT
|
|
174
222
|
type::string(id) AS id,
|
|
175
223
|
name,
|
|
@@ -178,9 +226,13 @@ class LearnedSkillService {
|
|
|
178
226
|
confidence,
|
|
179
227
|
vector::similarity::cosine(embedding, $embedding) AS similarity
|
|
180
228
|
FROM ${TABLES.LEARNED_SKILL}
|
|
181
|
-
WHERE
|
|
229
|
+
WHERE organizationId = $organizationId
|
|
230
|
+
AND status IN ['learned', 'verified', 'promoted']
|
|
231
|
+
AND archivedAt IS NONE
|
|
232
|
+
AND confidence >= $minConfidence
|
|
233
|
+
AND (agentId IS NONE OR agentId = $agentId)
|
|
234
|
+
AND embedding <|${params.limit}|> $embedding
|
|
182
235
|
ORDER BY similarity DESC
|
|
183
|
-
LIMIT $limit
|
|
184
236
|
`
|
|
185
237
|
|
|
186
238
|
const rows = await databaseService.query<unknown>(
|
|
@@ -189,9 +241,9 @@ class LearnedSkillService {
|
|
|
189
241
|
embedding: queryEmbedding,
|
|
190
242
|
agentId: params.agentId,
|
|
191
243
|
minConfidence: params.minConfidence,
|
|
192
|
-
limit: params.limit,
|
|
193
244
|
}),
|
|
194
245
|
)
|
|
246
|
+
timer.step('knn-query')
|
|
195
247
|
|
|
196
248
|
return rows.map((row) => SearchResultRowSchema.parse(row)).filter((row) => row.similarity >= 0.3)
|
|
197
249
|
}
|
|
@@ -253,24 +305,15 @@ class LearnedSkillService {
|
|
|
253
305
|
if (descEmbedding.length === 0) return null
|
|
254
306
|
|
|
255
307
|
const sql = `
|
|
256
|
-
LET $candidateRows = (
|
|
257
|
-
SELECT
|
|
258
|
-
id,
|
|
259
|
-
vector::distance::knn() AS distance
|
|
260
|
-
FROM ${TABLES.LEARNED_SKILL}
|
|
261
|
-
WHERE organizationId = $organizationId
|
|
262
|
-
AND status IN ['learned', 'verified', 'promoted']
|
|
263
|
-
AND archivedAt IS NONE
|
|
264
|
-
AND embedding <|3|> $embedding
|
|
265
|
-
ORDER BY distance ASC
|
|
266
|
-
);
|
|
267
|
-
|
|
268
308
|
SELECT *,
|
|
269
309
|
type::string(id) AS id,
|
|
270
310
|
type::string(organizationId) AS organizationId,
|
|
271
311
|
vector::similarity::cosine(embedding, $embedding) AS similarity
|
|
272
312
|
FROM ${TABLES.LEARNED_SKILL}
|
|
273
|
-
WHERE
|
|
313
|
+
WHERE organizationId = $organizationId
|
|
314
|
+
AND status IN ['learned', 'verified', 'promoted']
|
|
315
|
+
AND archivedAt IS NONE
|
|
316
|
+
AND embedding <|3|> $embedding
|
|
274
317
|
ORDER BY similarity DESC
|
|
275
318
|
LIMIT 1
|
|
276
319
|
`
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
|
|
3
3
|
import { agentRoster } from '../config/agent-defaults'
|
|
4
|
-
import { env } from '../config/env-shapes'
|
|
5
4
|
import { aiLogger } from '../config/logger'
|
|
6
5
|
import { Memory } from '../db/memory'
|
|
7
6
|
import { isUniqueIndexConflict } from '../db/memory-store.helpers'
|
|
@@ -24,6 +23,7 @@ import {
|
|
|
24
23
|
executeScopedRetrieval,
|
|
25
24
|
scopedRetrievalToMap,
|
|
26
25
|
} from '../runtime/retrieval-adapters'
|
|
26
|
+
import { getRuntimeConfig } from '../runtime/runtime-config'
|
|
27
27
|
import { createMemoryRerankerAgent, memoryRerankerPrompt } from '../system-agents/memory-reranker.agent'
|
|
28
28
|
import { createOrgMemoryAgent, orgMemoryPrompt } from '../system-agents/memory.agent'
|
|
29
29
|
import { assessMemoryImportance, clampMemoryImportance } from './memory-assessment.service'
|
|
@@ -304,7 +304,7 @@ class MemoryService {
|
|
|
304
304
|
scopeId: string
|
|
305
305
|
memoryType: MemoryType
|
|
306
306
|
}): Promise<string> {
|
|
307
|
-
const limit =
|
|
307
|
+
const limit = getRuntimeConfig().memory.searchK
|
|
308
308
|
const candidateLimit = getCandidateLimit(limit)
|
|
309
309
|
|
|
310
310
|
const candidates = await memory.searchCandidates(query, { scopeId, limit: candidateLimit, memoryType })
|
|
@@ -362,7 +362,8 @@ class MemoryService {
|
|
|
362
362
|
aiLogger.info`[MEMORY_DEBUG] searchOrganizationMemoriesRaw - orgId: "${orgId}", scopeId: "${orgScopeId}"`
|
|
363
363
|
const memory = this.getOrgMemory(orgId)
|
|
364
364
|
const fastMode = options?.fastMode ?? true
|
|
365
|
-
const
|
|
365
|
+
const searchK = getRuntimeConfig().memory.searchK
|
|
366
|
+
const limit = options?.limit ?? (fastMode ? Math.min(searchK, 4) : searchK)
|
|
366
367
|
|
|
367
368
|
try {
|
|
368
369
|
const candidates = await memory.searchCandidates(query, {
|
|
@@ -489,7 +490,7 @@ class MemoryService {
|
|
|
489
490
|
fastMode?: boolean
|
|
490
491
|
allowMultiScopeRerank?: boolean
|
|
491
492
|
}): Promise<string> {
|
|
492
|
-
const limit = Math.min(
|
|
493
|
+
const limit = Math.min(getRuntimeConfig().memory.searchK, MAX_MEMORY_RESULTS_PER_SCOPE)
|
|
493
494
|
const candidateLimit = fastMode ? limit : getCandidateLimit(limit)
|
|
494
495
|
const orgScopeId = scopeId(ORG_SCOPE_PREFIX, orgId)
|
|
495
496
|
const orgMemory = this.getOrgMemory(orgId)
|
|
@@ -6,7 +6,7 @@ import { workstreamMessageService } from './workstream-message.service'
|
|
|
6
6
|
|
|
7
7
|
const APPROVAL_VERIFICATION_MESSAGE_WINDOW = 20
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type VerifyMutatingApproval = (params: {
|
|
10
10
|
workstreamId: string
|
|
11
11
|
approvalReason: string
|
|
12
12
|
approvalToken: string
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PlanApprovalSchema } from '@lota-sdk/shared
|
|
2
|
-
import type { PlanApprovalRecord, PlanApprovalStatus } from '@lota-sdk/shared
|
|
1
|
+
import { PlanApprovalSchema } from '@lota-sdk/shared'
|
|
2
|
+
import type { PlanApprovalRecord, PlanApprovalStatus } from '@lota-sdk/shared'
|
|
3
3
|
import { RecordId } from 'surrealdb'
|
|
4
4
|
|
|
5
5
|
import type { RecordIdInput } from '../db/record-id'
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { PlanArtifactSchema } from '@lota-sdk/shared
|
|
2
|
-
import type { PlanArtifactRecord } from '@lota-sdk/shared
|
|
3
|
-
import type { PlanArtifactSubmission } from '@lota-sdk/shared/schemas/tools'
|
|
1
|
+
import { PlanArtifactSchema } from '@lota-sdk/shared'
|
|
2
|
+
import type { PlanArtifactRecord, PlanArtifactSubmission } from '@lota-sdk/shared'
|
|
4
3
|
import { RecordId } from 'surrealdb'
|
|
5
4
|
|
|
6
5
|
import type { RecordIdInput } from '../db/record-id'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PlanCheckpointSchema } from '@lota-sdk/shared
|
|
2
|
-
import type { PlanCheckpointRecord, PlanRunStatus } from '@lota-sdk/shared
|
|
1
|
+
import { PlanCheckpointSchema } from '@lota-sdk/shared'
|
|
2
|
+
import type { PlanCheckpointRecord, PlanRunStatus } from '@lota-sdk/shared'
|
|
3
3
|
import { RecordId } from 'surrealdb'
|
|
4
4
|
|
|
5
5
|
import type { RecordIdInput } from '../db/record-id'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PlanDraft, PlanNodeSpec, PlanNodeSpecRecord } from '@lota-sdk/shared
|
|
1
|
+
import type { PlanDraft, PlanNodeSpec, PlanNodeSpecRecord } from '@lota-sdk/shared'
|
|
2
2
|
|
|
3
3
|
import { planValidatorService } from './plan-validator.service'
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ export interface CompiledPlanNode {
|
|
|
9
9
|
downstreamNodeIds: string[]
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
interface CompiledPlanDraft {
|
|
13
13
|
draft: PlanDraft
|
|
14
14
|
nodes: CompiledPlanNode[]
|
|
15
15
|
}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PlanEventSchema,
|
|
3
|
-
PlanNodeAttemptSchema,
|
|
4
|
-
PlanNodeRunSchema,
|
|
5
|
-
PlanRunSchema,
|
|
6
|
-
PlanValidationIssueSchema,
|
|
7
|
-
} from '@lota-sdk/shared/schemas/execution-plan'
|
|
8
1
|
import type {
|
|
2
|
+
ExecutionPlanToolResultData,
|
|
9
3
|
PlanEventRecord,
|
|
10
4
|
PlanEventType,
|
|
11
5
|
PlanFailureAction,
|
|
12
6
|
PlanFailureClass,
|
|
7
|
+
PlanNodeResultSubmission,
|
|
13
8
|
PlanNodeRunRecord,
|
|
14
9
|
PlanNodeSpecRecord,
|
|
15
10
|
PlanRunRecord,
|
|
16
11
|
PlanSpecRecord,
|
|
17
12
|
PlanValidationIssueRecord,
|
|
18
13
|
SerializableExecutionPlan,
|
|
19
|
-
} from '@lota-sdk/shared
|
|
20
|
-
import
|
|
14
|
+
} from '@lota-sdk/shared'
|
|
15
|
+
import {
|
|
16
|
+
PlanEventSchema,
|
|
17
|
+
PlanNodeAttemptSchema,
|
|
18
|
+
PlanNodeRunSchema,
|
|
19
|
+
PlanRunSchema,
|
|
20
|
+
PlanValidationIssueSchema,
|
|
21
|
+
} from '@lota-sdk/shared'
|
|
21
22
|
import { RecordId } from 'surrealdb'
|
|
22
23
|
|
|
23
24
|
import type { RecordIdInput } from '../db/record-id'
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
PlanRunSchema,
|
|
10
10
|
PlanSpecSchema,
|
|
11
11
|
PlanValidationIssueSchema,
|
|
12
|
-
} from '@lota-sdk/shared
|
|
12
|
+
} from '@lota-sdk/shared'
|
|
13
13
|
import type {
|
|
14
14
|
PlanApprovalRecord,
|
|
15
15
|
PlanArtifactRecord,
|
|
@@ -29,7 +29,7 @@ import type {
|
|
|
29
29
|
SerializablePlanEvent,
|
|
30
30
|
SerializablePlanNode,
|
|
31
31
|
SerializablePlanValidationIssue,
|
|
32
|
-
} from '@lota-sdk/shared
|
|
32
|
+
} from '@lota-sdk/shared'
|
|
33
33
|
|
|
34
34
|
import type { RecordIdInput } from '../db/record-id'
|
|
35
35
|
import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
@@ -3,10 +3,10 @@ import type {
|
|
|
3
3
|
PlanDataSchema,
|
|
4
4
|
PlanDraft,
|
|
5
5
|
PlanFailureClass,
|
|
6
|
+
PlanNodeResultSubmission,
|
|
6
7
|
PlanNodeSpec,
|
|
7
8
|
PlanValidationIssueSeverity,
|
|
8
|
-
} from '@lota-sdk/shared
|
|
9
|
-
import type { PlanNodeResultSubmission } from '@lota-sdk/shared/schemas/tools'
|
|
9
|
+
} from '@lota-sdk/shared'
|
|
10
10
|
|
|
11
11
|
const STRUCTURAL_NODE_TYPES = new Set(['switch', 'join'])
|
|
12
12
|
const HUMAN_NODE_TYPES = new Set(['human-input', 'human-approval', 'human-review-edit', 'human-decision'])
|
|
@@ -19,12 +19,12 @@ export interface PlanValidationIssueInput {
|
|
|
19
19
|
nodeId?: string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
interface DraftValidationResult {
|
|
23
23
|
blocking: PlanValidationIssueInput[]
|
|
24
24
|
warnings: PlanValidationIssueInput[]
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
interface NodeResultValidationResult {
|
|
28
28
|
blocking: PlanValidationIssueInput[]
|
|
29
29
|
warnings: PlanValidationIssueInput[]
|
|
30
30
|
failureClass: PlanFailureClass | null
|
|
@@ -8,13 +8,13 @@ import {
|
|
|
8
8
|
RecentActivitySchema,
|
|
9
9
|
RecentActivitySourceSchema,
|
|
10
10
|
RecentActivityTitleSourceSchema,
|
|
11
|
-
} from '@lota-sdk/shared
|
|
11
|
+
} from '@lota-sdk/shared'
|
|
12
12
|
import type {
|
|
13
13
|
RecentActivity,
|
|
14
14
|
RecentActivityEvent,
|
|
15
15
|
RecentActivityEventInput,
|
|
16
16
|
RecentActivitySource,
|
|
17
|
-
} from '@lota-sdk/shared
|
|
17
|
+
} from '@lota-sdk/shared'
|
|
18
18
|
import { RecordId } from 'surrealdb'
|
|
19
19
|
import { z } from 'zod'
|
|
20
20
|
|
|
@@ -83,18 +83,16 @@ function buildDeterministicRecordId(table: string, key: string): RecordId {
|
|
|
83
83
|
return new RecordId(table, digest)
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
function
|
|
87
|
-
return existing?.titleSource === '
|
|
86
|
+
function shouldKeepExistingAgentTitle(existing: RecentActivityRow | null): boolean {
|
|
87
|
+
return existing?.titleSource === 'agent' && compactWhitespace(existing.title).length > 0
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function buildRecentActivityAreaKey(
|
|
91
|
-
row: Pick<RecentActivityRow, '
|
|
91
|
+
row: Pick<RecentActivityRow, 'targetKind' | 'targetId' | 'kind' | 'mergeKey' | 'metadata'>,
|
|
92
92
|
): string {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (target.chat) return `workstream:${target.chat}`
|
|
97
|
-
if (target.agent) return `agent:${target.agent}`
|
|
93
|
+
if (row.targetId) {
|
|
94
|
+
return `${row.targetKind}:${row.targetId}`
|
|
95
|
+
}
|
|
98
96
|
|
|
99
97
|
const normalizedWebsiteUrl = row.metadata?.normalizedWebsiteUrl
|
|
100
98
|
if (row.kind === 'website-intelligence.viewed' && normalizedWebsiteUrl) {
|
|
@@ -230,8 +228,8 @@ class RecentActivityService {
|
|
|
230
228
|
{ mutation: 'merge' },
|
|
231
229
|
)
|
|
232
230
|
|
|
233
|
-
const
|
|
234
|
-
const visibleTitle =
|
|
231
|
+
const keepExistingAgentTitle = shouldKeepExistingAgentTitle(existingRecent)
|
|
232
|
+
const visibleTitle = keepExistingAgentTitle && existingRecent ? existingRecent.title : parsedEvent.title
|
|
235
233
|
const recentRow = await databaseService.upsert(
|
|
236
234
|
TABLES.RECENT_ACTIVITY,
|
|
237
235
|
recentRecordId,
|
|
@@ -244,7 +242,7 @@ class RecentActivityService {
|
|
|
244
242
|
targetId: parsedEvent.targetId,
|
|
245
243
|
title: visibleTitle,
|
|
246
244
|
systemTitle: parsedEvent.title,
|
|
247
|
-
titleSource:
|
|
245
|
+
titleSource: keepExistingAgentTitle ? 'agent' : 'system',
|
|
248
246
|
sourceLabel: parsedEvent.sourceLabel,
|
|
249
247
|
deepLink: parsedEvent.deepLink,
|
|
250
248
|
metadata: parsedEvent.metadata,
|
|
@@ -326,7 +324,7 @@ class RecentActivityService {
|
|
|
326
324
|
const updated = await databaseService.update(
|
|
327
325
|
TABLES.RECENT_ACTIVITY,
|
|
328
326
|
activityRef,
|
|
329
|
-
{ title: nextTitle, titleSource: '
|
|
327
|
+
{ title: nextTitle, titleSource: 'agent', titleRefinedAt: new Date() },
|
|
330
328
|
RecentActivityRowSchema,
|
|
331
329
|
{ mutation: 'merge' },
|
|
332
330
|
)
|
|
@@ -365,7 +363,7 @@ class RecentActivityService {
|
|
|
365
363
|
return activity.titleSource === 'system'
|
|
366
364
|
}
|
|
367
365
|
|
|
368
|
-
|
|
366
|
+
isAgentTitleUseful(params: { currentTitle: string; systemTitle: string; candidateTitle: string }): boolean {
|
|
369
367
|
const candidate = compactWhitespace(params.candidateTitle)
|
|
370
368
|
if (!candidate) return false
|
|
371
369
|
|
|
@@ -385,7 +383,7 @@ class RecentActivityService {
|
|
|
385
383
|
'follow up',
|
|
386
384
|
'conversation',
|
|
387
385
|
'chat',
|
|
388
|
-
'
|
|
386
|
+
'agent task',
|
|
389
387
|
'recent activity',
|
|
390
388
|
'workstream update',
|
|
391
389
|
])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SdkUser, SdkUserRecord } from '@lota-sdk/shared
|
|
2
|
-
import { sdkUserRecordSchema, sdkUserSchema } from '@lota-sdk/shared
|
|
1
|
+
import type { SdkUser, SdkUserRecord } from '@lota-sdk/shared'
|
|
2
|
+
import { sdkUserRecordSchema, sdkUserSchema } from '@lota-sdk/shared'
|
|
3
3
|
|
|
4
4
|
import { BaseService } from '../db/base.service'
|
|
5
5
|
import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { toTimestamp, withCreatedAtMetadata } from '@lota-sdk/shared
|
|
2
|
-
import {
|
|
3
|
-
import type { ChatMessage } from '@lota-sdk/shared/schemas/chat-message'
|
|
1
|
+
import { parseRowMetadata, toTimestamp, withCreatedAtMetadata } from '@lota-sdk/shared'
|
|
2
|
+
import type { ChatMessage } from '@lota-sdk/shared'
|
|
4
3
|
import { RecordId, surql } from 'surrealdb'
|
|
5
4
|
import { z } from 'zod'
|
|
6
5
|
|