@lota-sdk/core 0.4.3 → 0.4.5
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/infrastructure/schema/02_execution_plan.surql +4 -0
- package/package.json +2 -2
- package/src/ai-gateway/ai-gateway.ts +0 -11
- package/src/config/background-processing.ts +0 -9
- package/src/config/model-constants.ts +0 -1
- package/src/create-runtime.ts +0 -2
- package/src/db/service.ts +7 -25
- package/src/queues/autonomous-job.queue.ts +0 -4
- package/src/runtime/execution-plan.ts +2 -7
- package/src/services/agent-activity.service.ts +35 -5
- package/src/services/artifact.service.ts +12 -14
- package/src/services/autonomous-job.service.ts +8 -12
- package/src/services/execution-plan.service.ts +397 -41
- package/src/services/global-orchestrator.service.ts +1 -1
- package/src/services/ownership-dispatcher.service.ts +1 -1
- package/src/services/plan-agent-query.service.ts +4 -3
- package/src/services/plan-builder.service.ts +1 -6
- package/src/services/plan-deadline.service.ts +8 -9
- package/src/services/plan-run-data.ts +70 -4
- package/src/services/plan-run.service.ts +28 -1
- package/src/services/plan-scheduler.service.ts +4 -4
- package/src/services/plan-template.service.ts +6 -0
- package/src/tools/execution-plan.tool.ts +13 -2
- package/src/tools/index.ts +1 -0
- package/src/tools/plan-approval.tool.ts +66 -0
- package/src/workers/worker-utils.ts +0 -68
|
@@ -86,7 +86,9 @@ DEFINE TABLE IF NOT EXISTS planRun SCHEMAFULL;
|
|
|
86
86
|
DEFINE FIELD IF NOT EXISTS planSpecId ON TABLE planRun TYPE record<planSpec> REFERENCE ON DELETE CASCADE;
|
|
87
87
|
DEFINE FIELD IF NOT EXISTS organizationId ON TABLE planRun TYPE record<organization>;
|
|
88
88
|
DEFINE FIELD IF NOT EXISTS threadId ON TABLE planRun TYPE record<thread> REFERENCE ON DELETE CASCADE;
|
|
89
|
+
DEFINE FIELD IF NOT EXISTS sourceThreadId ON TABLE planRun TYPE option<record<thread>>;
|
|
89
90
|
DEFINE FIELD IF NOT EXISTS leadAgentId ON TABLE planRun TYPE string;
|
|
91
|
+
DEFINE FIELD IF NOT EXISTS createdByAgentId ON TABLE planRun TYPE option<string>;
|
|
90
92
|
DEFINE FIELD IF NOT EXISTS status ON TABLE planRun TYPE string;
|
|
91
93
|
DEFINE FIELD IF NOT EXISTS currentNodeId ON TABLE planRun TYPE option<string>;
|
|
92
94
|
DEFINE FIELD IF NOT EXISTS waitingNodeId ON TABLE planRun TYPE option<string>;
|
|
@@ -103,7 +105,9 @@ DEFINE FIELD IF NOT EXISTS completedAt ON TABLE planRun TYPE option<datetime>;
|
|
|
103
105
|
|
|
104
106
|
DEFINE INDEX IF NOT EXISTS planRunOrgIdx ON TABLE planRun COLUMNS organizationId;
|
|
105
107
|
DEFINE INDEX IF NOT EXISTS planRunThreadIdx ON TABLE planRun COLUMNS threadId;
|
|
108
|
+
DEFINE INDEX IF NOT EXISTS planRunSourceThreadIdx ON TABLE planRun COLUMNS sourceThreadId;
|
|
106
109
|
DEFINE INDEX IF NOT EXISTS planRunThreadStatusIdx ON TABLE planRun COLUMNS threadId, status;
|
|
110
|
+
DEFINE INDEX IF NOT EXISTS planRunSourceThreadStatusIdx ON TABLE planRun COLUMNS sourceThreadId, status;
|
|
107
111
|
DEFINE INDEX IF NOT EXISTS planRunSpecIdx ON TABLE planRun COLUMNS planSpecId;
|
|
108
112
|
|
|
109
113
|
DEFINE TABLE IF NOT EXISTS planNodeRun SCHEMAFULL;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lota-sdk/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@chat-adapter/slack": "^4.23.0",
|
|
33
33
|
"@chat-adapter/state-ioredis": "^4.23.0",
|
|
34
34
|
"@logtape/logtape": "^2.0.5",
|
|
35
|
-
"@lota-sdk/shared": "0.4.
|
|
35
|
+
"@lota-sdk/shared": "0.4.5",
|
|
36
36
|
"@mendable/firecrawl-js": "^4.18.1",
|
|
37
37
|
"@surrealdb/node": "^3.0.3",
|
|
38
38
|
"ai": "^6.0.145",
|
|
@@ -305,17 +305,6 @@ export function injectAiGatewayExtraParamsRequestBody(
|
|
|
305
305
|
return JSON.stringify({ ...parsed, extra_params: mergedExtraParams })
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
export function injectAiGatewayOpenAIPromptCacheRetentionRequestBody(
|
|
309
|
-
body: BodyInit | null | undefined,
|
|
310
|
-
): BodyInit | null | undefined {
|
|
311
|
-
const parsed = parseAiGatewayJsonRequestBody(body)
|
|
312
|
-
if (!parsed) return body
|
|
313
|
-
if (!readString(parsed.model)?.startsWith('openai/')) return body
|
|
314
|
-
if (readString(parsed.prompt_cache_retention) !== null) return body
|
|
315
|
-
|
|
316
|
-
return JSON.stringify({ ...parsed, prompt_cache_retention: OPENAI_PROMPT_CACHE_RETENTION })
|
|
317
|
-
}
|
|
318
|
-
|
|
319
308
|
function createAiGatewayFetch(extraParams?: AiGatewayExtraParams): typeof fetch {
|
|
320
309
|
const fetchWithMutations = (input: RequestInfo | URL, init?: RequestInit | BunFetchRequestInit) => {
|
|
321
310
|
const parsedBody = parseAiGatewayJsonRequestBody(init?.body)
|
|
@@ -14,15 +14,6 @@ const DEFAULT_CONFIG: BackgroundProcessingConfig = {
|
|
|
14
14
|
|
|
15
15
|
let resolvedConfig: BackgroundProcessingConfig = { ...DEFAULT_CONFIG }
|
|
16
16
|
|
|
17
|
-
export function configureBackgroundProcessing(config?: Partial<BackgroundProcessingConfig>): void {
|
|
18
|
-
resolvedConfig = {
|
|
19
|
-
memoryExtractionFrequency: config?.memoryExtractionFrequency ?? DEFAULT_CONFIG.memoryExtractionFrequency,
|
|
20
|
-
skillExtractionFrequency: config?.skillExtractionFrequency ?? DEFAULT_CONFIG.skillExtractionFrequency,
|
|
21
|
-
memoryDigestFrequency: config?.memoryDigestFrequency ?? DEFAULT_CONFIG.memoryDigestFrequency,
|
|
22
|
-
memoryConsolidationFrequency: config?.memoryConsolidationFrequency ?? DEFAULT_CONFIG.memoryConsolidationFrequency,
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
17
|
export function getBackgroundProcessingConfig(): BackgroundProcessingConfig {
|
|
27
18
|
return resolvedConfig
|
|
28
19
|
}
|
|
@@ -8,7 +8,6 @@ export {
|
|
|
8
8
|
OPENROUTER_LOW_REASONING_PROVIDER_OPTIONS,
|
|
9
9
|
OPENROUTER_MEDIUM_REASONING_PROVIDER_OPTIONS,
|
|
10
10
|
OPENROUTER_MINIMAL_REASONING_PROVIDER_OPTIONS,
|
|
11
|
-
OPENROUTER_STRUCTURED_REASONING_MODEL_ID,
|
|
12
11
|
OPENROUTER_TEAM_AGENT_MODEL_ID,
|
|
13
12
|
OPENROUTER_WEB_RESEARCH_MODEL_ID,
|
|
14
13
|
OPENROUTER_XHIGH_REASONING_PROVIDER_OPTIONS,
|
package/src/create-runtime.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { ChatMessage } from '@lota-sdk/shared'
|
|
|
2
2
|
|
|
3
3
|
import { configureEmbeddingCache } from './ai/embedding-cache'
|
|
4
4
|
import { configureAgentFactory, configureAgents } from './config/agent-defaults'
|
|
5
|
-
import { configureBackgroundProcessing } from './config/background-processing'
|
|
6
5
|
import { configureLotaLogger } from './config/logger'
|
|
7
6
|
import { configureThreads } from './config/thread-defaults'
|
|
8
7
|
import { ensureRecordId } from './db/record-id'
|
|
@@ -251,7 +250,6 @@ export async function createLotaRuntime(config: LotaRuntimeConfig): Promise<Lota
|
|
|
251
250
|
const redisManager = createRedisConnectionManager({ url: runtimeConfig.redis.url })
|
|
252
251
|
setRedisConnectionManager(redisManager)
|
|
253
252
|
configureEmbeddingCache(redisManager.getConnection(), runtimeConfig.memory.embeddingCacheTtlSeconds)
|
|
254
|
-
configureBackgroundProcessing()
|
|
255
253
|
configureSocialChatHistory({ keyPrefix: runtimeConfig.socialChat?.historyRedisKeyPrefix })
|
|
256
254
|
|
|
257
255
|
const socialChatAgentId = runtimeConfig.socialChat?.agentId?.trim() || 'socialChat'
|
package/src/db/service.ts
CHANGED
|
@@ -44,8 +44,6 @@ export interface SurrealDatabaseLogger {
|
|
|
44
44
|
error?: (message: string) => void
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
export type BoundQueryLike = { query: string; bindings?: Record<string, unknown> }
|
|
48
|
-
|
|
49
47
|
interface FindManyOptions {
|
|
50
48
|
limit?: number
|
|
51
49
|
offset?: number
|
|
@@ -91,18 +89,6 @@ function configureMutation(
|
|
|
91
89
|
return builder.merge(data)
|
|
92
90
|
}
|
|
93
91
|
|
|
94
|
-
function isBoundQueryLike(value: unknown): value is BoundQueryLike {
|
|
95
|
-
if (!isRecord(value)) {
|
|
96
|
-
return false
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (typeof value.query !== 'string') {
|
|
100
|
-
return false
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return value.bindings === undefined || isRecord(value.bindings)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
92
|
const CONNECT_MAX_ATTEMPTS = 5
|
|
107
93
|
const CONNECT_RETRY_BASE_DELAY_MS = 100
|
|
108
94
|
const CONNECT_RETRY_JITTER_MS = 50
|
|
@@ -396,11 +382,7 @@ export class SurrealDBService {
|
|
|
396
382
|
return { clause: clauses.join(' AND '), bindings }
|
|
397
383
|
}
|
|
398
384
|
|
|
399
|
-
private normalizeBoundQuery(query: BoundQuery
|
|
400
|
-
if (!(query instanceof BoundQuery) && !isBoundQueryLike(query)) {
|
|
401
|
-
throw new SurrealDBError('Invalid query object: expected a BoundQuery-like value')
|
|
402
|
-
}
|
|
403
|
-
|
|
385
|
+
private normalizeBoundQuery(query: BoundQuery): BoundQuery {
|
|
404
386
|
return new BoundQuery(query.query, this.normalizeBindings(query.bindings))
|
|
405
387
|
}
|
|
406
388
|
|
|
@@ -533,7 +515,7 @@ export class SurrealDBService {
|
|
|
533
515
|
private wrapTransaction(tx: SurrealTransaction): DatabaseTransaction {
|
|
534
516
|
return {
|
|
535
517
|
query: async (query: unknown) => {
|
|
536
|
-
const boundQuery = this.normalizeBoundQuery(query as BoundQuery
|
|
518
|
+
const boundQuery = this.normalizeBoundQuery(query as BoundQuery)
|
|
537
519
|
const queryText = this.resolveQueryText(boundQuery)
|
|
538
520
|
|
|
539
521
|
try {
|
|
@@ -578,16 +560,16 @@ export class SurrealDBService {
|
|
|
578
560
|
}
|
|
579
561
|
}
|
|
580
562
|
|
|
581
|
-
private resolveQueryText(query: BoundQuery
|
|
563
|
+
private resolveQueryText(query: BoundQuery): string {
|
|
582
564
|
return query.query
|
|
583
565
|
}
|
|
584
566
|
|
|
585
|
-
async query<T>(query: BoundQuery
|
|
567
|
+
async query<T>(query: BoundQuery): Promise<T[]> {
|
|
586
568
|
const statements = await this.queryAll<T>(query)
|
|
587
569
|
return statements.at(0) ?? []
|
|
588
570
|
}
|
|
589
571
|
|
|
590
|
-
async queryAll<T>(query: BoundQuery
|
|
572
|
+
async queryAll<T>(query: BoundQuery, schema?: z.ZodTypeAny): Promise<T[][]> {
|
|
591
573
|
const client = await this.ensureConnected()
|
|
592
574
|
const boundQuery = this.normalizeBoundQuery(query)
|
|
593
575
|
const queryText = this.resolveQueryText(boundQuery)
|
|
@@ -607,13 +589,13 @@ export class SurrealDBService {
|
|
|
607
589
|
}
|
|
608
590
|
}
|
|
609
591
|
|
|
610
|
-
async queryOne<T extends z.ZodTypeAny>(query: BoundQuery
|
|
592
|
+
async queryOne<T extends z.ZodTypeAny>(query: BoundQuery, schema: T): Promise<z.infer<T> | null> {
|
|
611
593
|
const results = await this.query<unknown>(query)
|
|
612
594
|
const first = results.at(0)
|
|
613
595
|
return first ? this.parseSchema(schema, first) : null
|
|
614
596
|
}
|
|
615
597
|
|
|
616
|
-
async queryMany<T extends z.ZodTypeAny>(query: BoundQuery
|
|
598
|
+
async queryMany<T extends z.ZodTypeAny>(query: BoundQuery, schema: T): Promise<z.infer<T>[]> {
|
|
617
599
|
const results = await this.query<unknown>(query)
|
|
618
600
|
return results.map((row) => this.parseSchema(schema, row))
|
|
619
601
|
}
|
|
@@ -129,10 +129,6 @@ export function startAutonomousJobWorker(options: AutonomousJobWorkerOptions = {
|
|
|
129
129
|
return handle
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export function getAutonomousJobQueueHandle(): WorkerHandle {
|
|
133
|
-
return startAutonomousJobWorker()
|
|
134
|
-
}
|
|
135
|
-
|
|
136
132
|
if (import.meta.main) {
|
|
137
133
|
startAutonomousJobWorker()
|
|
138
134
|
}
|
|
@@ -16,9 +16,7 @@ function toExecutionPlanPromptSummaries(plans: SerializableExecutionPlan[]): Exe
|
|
|
16
16
|
return plans.map(({ runId, title }) => ({ runId, title }))
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function formatExecutionPlansForPrompt(plans: SerializableExecutionPlan[]): string
|
|
20
|
-
if (plans.length === 0) return undefined
|
|
21
|
-
|
|
19
|
+
function formatExecutionPlansForPrompt(plans: SerializableExecutionPlan[]): string {
|
|
22
20
|
const payload = { activePlans: toExecutionPlanPromptSummaries(plans), planCount: plans.length }
|
|
23
21
|
|
|
24
22
|
return ['<execution-plan-state>', JSON.stringify(payload, null, 2), '</execution-plan-state>'].join('\n')
|
|
@@ -26,10 +24,7 @@ function formatExecutionPlansForPrompt(plans: SerializableExecutionPlan[]): stri
|
|
|
26
24
|
|
|
27
25
|
export function buildExecutionPlanInstructionSections(plans: SerializableExecutionPlan[] | null | undefined): string[] {
|
|
28
26
|
const normalized = plans ?? []
|
|
29
|
-
|
|
30
|
-
const stateSection = formatExecutionPlansForPrompt(normalized)
|
|
31
|
-
if (stateSection) sections.push(stateSection)
|
|
32
|
-
return sections
|
|
27
|
+
return [EXECUTION_PLAN_AGENT_PROTOCOL_PROMPT, formatExecutionPlansForPrompt(normalized)]
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
export function createExecutionPlanInstructionSectionCache(params: {
|
|
@@ -41,6 +41,14 @@ type AgentActivityDeps = {
|
|
|
41
41
|
threadService: Pick<typeof threadService, 'listThreads'>
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
function isPendingPlanApproval(plan: SerializableExecutionPlan): boolean {
|
|
45
|
+
return plan.status === 'pending-approval'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function countPendingPlanApprovals(activePlans: ActivePlanEntry[]): number {
|
|
49
|
+
return activePlans.filter(({ plan }) => isPendingPlanApproval(plan)).length
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
function normalizeCardStatus(status: string): BoardColumnStatus {
|
|
45
53
|
if (status === 'pending' || status === 'scheduled') return 'ready'
|
|
46
54
|
if (status === 'partial') return 'completed'
|
|
@@ -145,9 +153,9 @@ export class AgentActivityService {
|
|
|
145
153
|
|
|
146
154
|
async getBoard(userRef: string, orgRef: string): Promise<PlanBoardResponse> {
|
|
147
155
|
const activePlans = await this.getAllActivePlans(userRef, orgRef)
|
|
148
|
-
const cards = activePlans
|
|
149
|
-
|
|
150
|
-
|
|
156
|
+
const cards = activePlans
|
|
157
|
+
.filter(({ plan }) => !isPendingPlanApproval(plan))
|
|
158
|
+
.flatMap(({ plan, thread }) => plan.nodes.map((node) => planNodeToCard(node, plan, thread.id, thread.title)))
|
|
151
159
|
|
|
152
160
|
const columns: PlanBoardColumn[] = BOARD_COLUMN_ORDER.map((status) => ({
|
|
153
161
|
status,
|
|
@@ -161,7 +169,7 @@ export class AgentActivityService {
|
|
|
161
169
|
totalNodes: cards.length,
|
|
162
170
|
completedNodes: cards.filter((card) => card.status === 'completed').length,
|
|
163
171
|
activePlanCount: activePlans.length,
|
|
164
|
-
pendingApprovalCount: cards.filter((card) => card.hasApproval).length,
|
|
172
|
+
pendingApprovalCount: countPendingPlanApprovals(activePlans) + cards.filter((card) => card.hasApproval).length,
|
|
165
173
|
},
|
|
166
174
|
}
|
|
167
175
|
}
|
|
@@ -187,8 +195,13 @@ export class AgentActivityService {
|
|
|
187
195
|
async getMyTasks(userRef: string, orgRef: string): Promise<MyTasksResponse> {
|
|
188
196
|
const activePlans = await this.getAllActivePlans(userRef, orgRef)
|
|
189
197
|
const tasks: PlanNodeCard[] = []
|
|
198
|
+
const pendingPlanApprovalCount = countPendingPlanApprovals(activePlans)
|
|
190
199
|
|
|
191
200
|
for (const { plan, thread } of activePlans) {
|
|
201
|
+
if (isPendingPlanApproval(plan)) {
|
|
202
|
+
continue
|
|
203
|
+
}
|
|
204
|
+
|
|
192
205
|
for (const node of plan.nodes) {
|
|
193
206
|
const humanOwned = node.owner.executorType === 'user'
|
|
194
207
|
const awaitingHuman = node.status === 'awaiting-human'
|
|
@@ -198,7 +211,7 @@ export class AgentActivityService {
|
|
|
198
211
|
}
|
|
199
212
|
}
|
|
200
213
|
|
|
201
|
-
return { tasks, pendingApprovalCount: tasks.filter((task) => task.hasApproval).length }
|
|
214
|
+
return { tasks, pendingApprovalCount: pendingPlanApprovalCount + tasks.filter((task) => task.hasApproval).length }
|
|
202
215
|
}
|
|
203
216
|
|
|
204
217
|
async getAgentActivity(userRef: string, orgRef: string): Promise<AgentActivityResponse> {
|
|
@@ -210,6 +223,23 @@ export class AgentActivityService {
|
|
|
210
223
|
}
|
|
211
224
|
|
|
212
225
|
for (const { plan, thread } of activePlans) {
|
|
226
|
+
if (isPendingPlanApproval(plan)) {
|
|
227
|
+
if (plan.leadAgentId.trim()) {
|
|
228
|
+
const leadEntry = this.ensureEntry(activityByAgent, plan.leadAgentId)
|
|
229
|
+
leadEntry.isLeadingActivePlan = true
|
|
230
|
+
this.ensureProjectEntry(leadEntry.projects, {
|
|
231
|
+
threadId: thread.id,
|
|
232
|
+
threadTitle: thread.title,
|
|
233
|
+
planRunId: plan.runId,
|
|
234
|
+
planTitle: plan.title,
|
|
235
|
+
status: plan.status,
|
|
236
|
+
})
|
|
237
|
+
leadEntry.isRunning = leadEntry.isRunning || thread.isRunning
|
|
238
|
+
leadEntry.lastActiveAt = maxIsoDate(leadEntry.lastActiveAt, thread.updatedAt)
|
|
239
|
+
}
|
|
240
|
+
continue
|
|
241
|
+
}
|
|
242
|
+
|
|
213
243
|
const involvedAgents = new Set<string>()
|
|
214
244
|
|
|
215
245
|
for (const node of plan.nodes) {
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
GetArtifactResult,
|
|
8
8
|
PublishArtifactArgs,
|
|
9
9
|
} from '@lota-sdk/shared'
|
|
10
|
+
import { BoundQuery } from 'surrealdb'
|
|
10
11
|
|
|
11
12
|
import type { RecordIdInput } from '../db/record-id'
|
|
12
13
|
import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
@@ -270,25 +271,25 @@ class ArtifactService {
|
|
|
270
271
|
|
|
271
272
|
let lastError: unknown = null
|
|
272
273
|
for (let attempt = 1; attempt <= ARTIFACT_PUBLISH_MAX_ATTEMPTS; attempt += 1) {
|
|
273
|
-
|
|
274
|
+
const publishAttemptState: { pendingStorageKey?: string } = {}
|
|
274
275
|
try {
|
|
275
276
|
return await databaseService.withTransaction(
|
|
276
277
|
async (tx) =>
|
|
277
278
|
await this.publishArtifactInTransaction(params, tx, {
|
|
278
279
|
onStorageWrite: (storageKey) => {
|
|
279
|
-
pendingStorageKey = storageKey
|
|
280
|
+
publishAttemptState.pendingStorageKey = storageKey
|
|
280
281
|
},
|
|
281
282
|
onStorageCleanup: (storageKey) => {
|
|
282
|
-
if (pendingStorageKey === storageKey) {
|
|
283
|
-
pendingStorageKey =
|
|
283
|
+
if (publishAttemptState.pendingStorageKey === storageKey) {
|
|
284
|
+
publishAttemptState.pendingStorageKey = undefined
|
|
284
285
|
}
|
|
285
286
|
},
|
|
286
287
|
}),
|
|
287
288
|
)
|
|
288
289
|
} catch (error) {
|
|
289
|
-
const storageKeyToCleanup = pendingStorageKey
|
|
290
|
-
pendingStorageKey =
|
|
291
|
-
if (storageKeyToCleanup
|
|
290
|
+
const storageKeyToCleanup = publishAttemptState.pendingStorageKey
|
|
291
|
+
publishAttemptState.pendingStorageKey = undefined
|
|
292
|
+
if (typeof storageKeyToCleanup === 'string') {
|
|
292
293
|
await generatedDocumentStorageService.deleteTextArtifact(storageKeyToCleanup).catch(() => undefined)
|
|
293
294
|
}
|
|
294
295
|
lastError = error
|
|
@@ -361,13 +362,10 @@ class ArtifactService {
|
|
|
361
362
|
async listBacklinks(artifact: Pick<ArtifactRecord, 'id' | 'organizationId'>): Promise<ArtifactRecord[]> {
|
|
362
363
|
const artifactId = recordIdToString(artifact.id, TABLES.ARTIFACT)
|
|
363
364
|
const records = await databaseService.queryMany(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
targetId: artifactId,
|
|
369
|
-
},
|
|
370
|
-
},
|
|
365
|
+
new BoundQuery(
|
|
366
|
+
`SELECT * FROM ${TABLES.ARTIFACT} WHERE organizationId = $organizationId AND references[*].targetId CONTAINS $targetId`,
|
|
367
|
+
{ organizationId: ensureRecordId(artifact.organizationId, TABLES.ORGANIZATION), targetId: artifactId },
|
|
368
|
+
),
|
|
371
369
|
ArtifactRecordSchema,
|
|
372
370
|
)
|
|
373
371
|
return records
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
} from '@lota-sdk/shared'
|
|
23
23
|
import type { Job } from 'bullmq'
|
|
24
24
|
import { CronExpressionParser } from 'cron-parser'
|
|
25
|
-
import { RecordId } from 'surrealdb'
|
|
25
|
+
import { BoundQuery, RecordId } from 'surrealdb'
|
|
26
26
|
import { z } from 'zod'
|
|
27
27
|
|
|
28
28
|
import { ensureRecordId, recordIdToString } from '../db/record-id'
|
|
@@ -262,17 +262,14 @@ class AutonomousJobService {
|
|
|
262
262
|
|
|
263
263
|
private async findRecoverableRunRow(autonomousJobId: RecordIdInput): Promise<AutonomousJobRunRow | null> {
|
|
264
264
|
const rows = await databaseService.queryMany(
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
new BoundQuery(
|
|
266
|
+
`SELECT * FROM ${TABLES.AUTONOMOUS_JOB_RUN}
|
|
267
267
|
WHERE autonomousJobId = $autonomousJobId
|
|
268
268
|
AND status IN $statuses
|
|
269
269
|
ORDER BY createdAt DESC
|
|
270
270
|
LIMIT 1`,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
statuses: ['queued', 'running'],
|
|
274
|
-
},
|
|
275
|
-
},
|
|
271
|
+
{ autonomousJobId: ensureRecordId(autonomousJobId, TABLES.AUTONOMOUS_JOB), statuses: ['queued', 'running'] },
|
|
272
|
+
),
|
|
276
273
|
AutonomousJobRunRowSchema,
|
|
277
274
|
)
|
|
278
275
|
|
|
@@ -371,10 +368,9 @@ class AutonomousJobService {
|
|
|
371
368
|
async recoverActiveJobs(now = new Date()): Promise<void> {
|
|
372
369
|
await databaseService.connect()
|
|
373
370
|
const activeRows = await databaseService.queryMany(
|
|
374
|
-
{
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
},
|
|
371
|
+
new BoundQuery(`SELECT * FROM ${TABLES.AUTONOMOUS_JOB} WHERE status = $status ORDER BY createdAt ASC`, {
|
|
372
|
+
status: 'active',
|
|
373
|
+
}),
|
|
378
374
|
AutonomousJobRowSchema,
|
|
379
375
|
)
|
|
380
376
|
|