@jamesaphoenix/tx-core 0.4.1
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/dist/db.d.ts +42 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +46 -0
- package/dist/db.js.map +1 -0
- package/dist/errors.d.ts +231 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +139 -0
- package/dist/errors.js.map +1 -0
- package/dist/id.d.ts +6 -0
- package/dist/id.d.ts.map +1 -0
- package/dist/id.js +21 -0
- package/dist/id.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/layer.d.ts +50 -0
- package/dist/layer.d.ts.map +1 -0
- package/dist/layer.js +155 -0
- package/dist/layer.js.map +1 -0
- package/dist/mappers/anchor.d.ts +14 -0
- package/dist/mappers/anchor.d.ts.map +1 -0
- package/dist/mappers/anchor.js +38 -0
- package/dist/mappers/anchor.js.map +1 -0
- package/dist/mappers/attempt.d.ts +15 -0
- package/dist/mappers/attempt.d.ts.map +1 -0
- package/dist/mappers/attempt.js +23 -0
- package/dist/mappers/attempt.js.map +1 -0
- package/dist/mappers/candidate.d.ts +23 -0
- package/dist/mappers/candidate.d.ts.map +1 -0
- package/dist/mappers/candidate.js +53 -0
- package/dist/mappers/candidate.js.map +1 -0
- package/dist/mappers/claim.d.ts +30 -0
- package/dist/mappers/claim.d.ts.map +1 -0
- package/dist/mappers/claim.js +32 -0
- package/dist/mappers/claim.js.map +1 -0
- package/dist/mappers/deduplication.d.ts +39 -0
- package/dist/mappers/deduplication.d.ts.map +1 -0
- package/dist/mappers/deduplication.js +53 -0
- package/dist/mappers/deduplication.js.map +1 -0
- package/dist/mappers/edge.d.ts +10 -0
- package/dist/mappers/edge.d.ts.map +1 -0
- package/dist/mappers/edge.js +19 -0
- package/dist/mappers/edge.js.map +1 -0
- package/dist/mappers/file-learning.d.ts +14 -0
- package/dist/mappers/file-learning.d.ts.map +1 -0
- package/dist/mappers/file-learning.js +75 -0
- package/dist/mappers/file-learning.js.map +1 -0
- package/dist/mappers/index.d.ts +17 -0
- package/dist/mappers/index.d.ts.map +1 -0
- package/dist/mappers/index.js +30 -0
- package/dist/mappers/index.js.map +1 -0
- package/dist/mappers/learning.d.ts +19 -0
- package/dist/mappers/learning.d.ts.map +1 -0
- package/dist/mappers/learning.js +41 -0
- package/dist/mappers/learning.js.map +1 -0
- package/dist/mappers/orchestrator-state.d.ts +33 -0
- package/dist/mappers/orchestrator-state.d.ts.map +1 -0
- package/dist/mappers/orchestrator-state.js +34 -0
- package/dist/mappers/orchestrator-state.js.map +1 -0
- package/dist/mappers/run.d.ts +32 -0
- package/dist/mappers/run.d.ts.map +1 -0
- package/dist/mappers/run.js +64 -0
- package/dist/mappers/run.js.map +1 -0
- package/dist/mappers/task.d.ts +23 -0
- package/dist/mappers/task.d.ts.map +1 -0
- package/dist/mappers/task.js +54 -0
- package/dist/mappers/task.js.map +1 -0
- package/dist/mappers/tracked-project.d.ts +15 -0
- package/dist/mappers/tracked-project.d.ts.map +1 -0
- package/dist/mappers/tracked-project.js +23 -0
- package/dist/mappers/tracked-project.js.map +1 -0
- package/dist/mappers/worker.d.ts +33 -0
- package/dist/mappers/worker.d.ts.map +1 -0
- package/dist/mappers/worker.js +35 -0
- package/dist/mappers/worker.js.map +1 -0
- package/dist/repo/anchor-repo.d.ts +52 -0
- package/dist/repo/anchor-repo.d.ts.map +1 -0
- package/dist/repo/anchor-repo.js +204 -0
- package/dist/repo/anchor-repo.js.map +1 -0
- package/dist/repo/attempt-repo.d.ts +25 -0
- package/dist/repo/attempt-repo.d.ts.map +1 -0
- package/dist/repo/attempt-repo.js +78 -0
- package/dist/repo/attempt-repo.js.map +1 -0
- package/dist/repo/candidate-repo.d.ts +16 -0
- package/dist/repo/candidate-repo.d.ts.map +1 -0
- package/dist/repo/candidate-repo.js +143 -0
- package/dist/repo/candidate-repo.js.map +1 -0
- package/dist/repo/claim-repo.d.ts +17 -0
- package/dist/repo/claim-repo.d.ts.map +1 -0
- package/dist/repo/claim-repo.js +62 -0
- package/dist/repo/claim-repo.js.map +1 -0
- package/dist/repo/deduplication-repo.d.ts +37 -0
- package/dist/repo/deduplication-repo.d.ts.map +1 -0
- package/dist/repo/deduplication-repo.js +133 -0
- package/dist/repo/deduplication-repo.js.map +1 -0
- package/dist/repo/dep-repo.d.ts +19 -0
- package/dist/repo/dep-repo.d.ts.map +1 -0
- package/dist/repo/dep-repo.js +104 -0
- package/dist/repo/dep-repo.js.map +1 -0
- package/dist/repo/edge-repo.d.ts +26 -0
- package/dist/repo/edge-repo.d.ts.map +1 -0
- package/dist/repo/edge-repo.js +227 -0
- package/dist/repo/edge-repo.js.map +1 -0
- package/dist/repo/file-learning-repo.d.ts +17 -0
- package/dist/repo/file-learning-repo.d.ts.map +1 -0
- package/dist/repo/file-learning-repo.js +60 -0
- package/dist/repo/file-learning-repo.js.map +1 -0
- package/dist/repo/index.d.ts +18 -0
- package/dist/repo/index.d.ts.map +1 -0
- package/dist/repo/index.js +18 -0
- package/dist/repo/index.js.map +1 -0
- package/dist/repo/learning-repo.d.ts +31 -0
- package/dist/repo/learning-repo.d.ts.map +1 -0
- package/dist/repo/learning-repo.js +165 -0
- package/dist/repo/learning-repo.js.map +1 -0
- package/dist/repo/orchestrator-state-repo.d.ts +27 -0
- package/dist/repo/orchestrator-state-repo.d.ts.map +1 -0
- package/dist/repo/orchestrator-state-repo.js +96 -0
- package/dist/repo/orchestrator-state-repo.js.map +1 -0
- package/dist/repo/run-repo.d.ts +31 -0
- package/dist/repo/run-repo.d.ts.map +1 -0
- package/dist/repo/run-repo.js +132 -0
- package/dist/repo/run-repo.js.map +1 -0
- package/dist/repo/task-repo.d.ts +21 -0
- package/dist/repo/task-repo.d.ts.map +1 -0
- package/dist/repo/task-repo.js +169 -0
- package/dist/repo/task-repo.js.map +1 -0
- package/dist/repo/tracked-project-repo.d.ts +16 -0
- package/dist/repo/tracked-project-repo.d.ts.map +1 -0
- package/dist/repo/tracked-project-repo.js +54 -0
- package/dist/repo/tracked-project-repo.js.map +1 -0
- package/dist/repo/worker-repo.d.ts +19 -0
- package/dist/repo/worker-repo.d.ts.map +1 -0
- package/dist/repo/worker-repo.js +72 -0
- package/dist/repo/worker-repo.js.map +1 -0
- package/dist/schemas/index.d.ts +8 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +7 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/sync.d.ts +296 -0
- package/dist/schemas/sync.d.ts.map +1 -0
- package/dist/schemas/sync.js +146 -0
- package/dist/schemas/sync.js.map +1 -0
- package/dist/schemas/worker.d.ts +77 -0
- package/dist/schemas/worker.d.ts.map +1 -0
- package/dist/schemas/worker.js +80 -0
- package/dist/schemas/worker.js.map +1 -0
- package/dist/services/anchor-service.d.ts +147 -0
- package/dist/services/anchor-service.d.ts.map +1 -0
- package/dist/services/anchor-service.js +540 -0
- package/dist/services/anchor-service.js.map +1 -0
- package/dist/services/anchor-verification.d.ts +94 -0
- package/dist/services/anchor-verification.d.ts.map +1 -0
- package/dist/services/anchor-verification.js +617 -0
- package/dist/services/anchor-verification.js.map +1 -0
- package/dist/services/ast-grep-service.d.ts +58 -0
- package/dist/services/ast-grep-service.d.ts.map +1 -0
- package/dist/services/ast-grep-service.js +356 -0
- package/dist/services/ast-grep-service.js.map +1 -0
- package/dist/services/attempt-service.d.ts +24 -0
- package/dist/services/attempt-service.d.ts.map +1 -0
- package/dist/services/attempt-service.js +55 -0
- package/dist/services/attempt-service.js.map +1 -0
- package/dist/services/auto-sync-service.d.ts +56 -0
- package/dist/services/auto-sync-service.d.ts.map +1 -0
- package/dist/services/auto-sync-service.js +66 -0
- package/dist/services/auto-sync-service.js.map +1 -0
- package/dist/services/candidate-extractor-service.d.ts +56 -0
- package/dist/services/candidate-extractor-service.d.ts.map +1 -0
- package/dist/services/candidate-extractor-service.js +365 -0
- package/dist/services/candidate-extractor-service.js.map +1 -0
- package/dist/services/claim-service.d.ts +52 -0
- package/dist/services/claim-service.d.ts.map +1 -0
- package/dist/services/claim-service.js +134 -0
- package/dist/services/claim-service.js.map +1 -0
- package/dist/services/daemon-service.d.ts +214 -0
- package/dist/services/daemon-service.d.ts.map +1 -0
- package/dist/services/daemon-service.js +522 -0
- package/dist/services/daemon-service.js.map +1 -0
- package/dist/services/deduplication-service.d.ts +67 -0
- package/dist/services/deduplication-service.d.ts.map +1 -0
- package/dist/services/deduplication-service.js +145 -0
- package/dist/services/deduplication-service.js.map +1 -0
- package/dist/services/dep-service.d.ts +14 -0
- package/dist/services/dep-service.d.ts.map +1 -0
- package/dist/services/dep-service.js +34 -0
- package/dist/services/dep-service.js.map +1 -0
- package/dist/services/diversifier-service.d.ts +46 -0
- package/dist/services/diversifier-service.d.ts.map +1 -0
- package/dist/services/diversifier-service.js +197 -0
- package/dist/services/diversifier-service.js.map +1 -0
- package/dist/services/edge-service.d.ts +78 -0
- package/dist/services/edge-service.d.ts.map +1 -0
- package/dist/services/edge-service.js +158 -0
- package/dist/services/edge-service.js.map +1 -0
- package/dist/services/embedding-service.d.ts +138 -0
- package/dist/services/embedding-service.d.ts.map +1 -0
- package/dist/services/embedding-service.js +318 -0
- package/dist/services/embedding-service.js.map +1 -0
- package/dist/services/feedback-tracker.d.ts +64 -0
- package/dist/services/feedback-tracker.d.ts.map +1 -0
- package/dist/services/feedback-tracker.js +110 -0
- package/dist/services/feedback-tracker.js.map +1 -0
- package/dist/services/file-learning-service.d.ts +17 -0
- package/dist/services/file-learning-service.d.ts.map +1 -0
- package/dist/services/file-learning-service.js +41 -0
- package/dist/services/file-learning-service.js.map +1 -0
- package/dist/services/file-watcher-service.d.ts +141 -0
- package/dist/services/file-watcher-service.d.ts.map +1 -0
- package/dist/services/file-watcher-service.js +278 -0
- package/dist/services/file-watcher-service.js.map +1 -0
- package/dist/services/graph-expansion.d.ts +155 -0
- package/dist/services/graph-expansion.d.ts.map +1 -0
- package/dist/services/graph-expansion.js +466 -0
- package/dist/services/graph-expansion.js.map +1 -0
- package/dist/services/hierarchy-service.d.ts +16 -0
- package/dist/services/hierarchy-service.d.ts.map +1 -0
- package/dist/services/hierarchy-service.js +66 -0
- package/dist/services/hierarchy-service.js.map +1 -0
- package/dist/services/index.d.ts +36 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +36 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/learning-service.d.ts +39 -0
- package/dist/services/learning-service.d.ts.map +1 -0
- package/dist/services/learning-service.js +151 -0
- package/dist/services/learning-service.js.map +1 -0
- package/dist/services/migration-service.d.ts +67 -0
- package/dist/services/migration-service.d.ts.map +1 -0
- package/dist/services/migration-service.js +144 -0
- package/dist/services/migration-service.js.map +1 -0
- package/dist/services/orchestrator-service.d.ts +52 -0
- package/dist/services/orchestrator-service.d.ts.map +1 -0
- package/dist/services/orchestrator-service.js +203 -0
- package/dist/services/orchestrator-service.js.map +1 -0
- package/dist/services/promotion-service.d.ts +67 -0
- package/dist/services/promotion-service.d.ts.map +1 -0
- package/dist/services/promotion-service.js +151 -0
- package/dist/services/promotion-service.js.map +1 -0
- package/dist/services/query-expansion-service.d.ts +55 -0
- package/dist/services/query-expansion-service.d.ts.map +1 -0
- package/dist/services/query-expansion-service.js +174 -0
- package/dist/services/query-expansion-service.js.map +1 -0
- package/dist/services/ready-service.d.ts +16 -0
- package/dist/services/ready-service.d.ts.map +1 -0
- package/dist/services/ready-service.js +70 -0
- package/dist/services/ready-service.js.map +1 -0
- package/dist/services/reranker-service.d.ts +51 -0
- package/dist/services/reranker-service.d.ts.map +1 -0
- package/dist/services/reranker-service.js +128 -0
- package/dist/services/reranker-service.js.map +1 -0
- package/dist/services/retriever-service.d.ts +49 -0
- package/dist/services/retriever-service.d.ts.map +1 -0
- package/dist/services/retriever-service.js +419 -0
- package/dist/services/retriever-service.js.map +1 -0
- package/dist/services/score-service.d.ts +43 -0
- package/dist/services/score-service.d.ts.map +1 -0
- package/dist/services/score-service.js +82 -0
- package/dist/services/score-service.js.map +1 -0
- package/dist/services/swarm-verification.d.ts +104 -0
- package/dist/services/swarm-verification.d.ts.map +1 -0
- package/dist/services/swarm-verification.js +400 -0
- package/dist/services/swarm-verification.js.map +1 -0
- package/dist/services/sync-service.d.ts +115 -0
- package/dist/services/sync-service.d.ts.map +1 -0
- package/dist/services/sync-service.js +350 -0
- package/dist/services/sync-service.js.map +1 -0
- package/dist/services/task-service.d.ts +22 -0
- package/dist/services/task-service.d.ts.map +1 -0
- package/dist/services/task-service.js +221 -0
- package/dist/services/task-service.js.map +1 -0
- package/dist/services/worker-process.d.ts +41 -0
- package/dist/services/worker-process.d.ts.map +1 -0
- package/dist/services/worker-process.js +280 -0
- package/dist/services/worker-process.js.map +1 -0
- package/dist/services/worker-service.d.ts +74 -0
- package/dist/services/worker-service.d.ts.map +1 -0
- package/dist/services/worker-service.js +148 -0
- package/dist/services/worker-service.js.map +1 -0
- package/dist/utils/glob.d.ts +15 -0
- package/dist/utils/glob.d.ts.map +1 -0
- package/dist/utils/glob.js +27 -0
- package/dist/utils/glob.js.map +1 -0
- package/dist/utils/math.d.ts +6 -0
- package/dist/utils/math.d.ts.map +1 -0
- package/dist/utils/math.js +21 -0
- package/dist/utils/math.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrchestratorService - PRD-018
|
|
3
|
+
*
|
|
4
|
+
* Manages orchestrator lifecycle and reconciliation loop.
|
|
5
|
+
* Uses Effect-TS patterns per DD-002.
|
|
6
|
+
*/
|
|
7
|
+
import { Context, Effect, Layer } from "effect";
|
|
8
|
+
import { OrchestratorStateRepository } from "../repo/orchestrator-state-repo.js";
|
|
9
|
+
import { TaskRepository } from "../repo/task-repo.js";
|
|
10
|
+
import { ClaimRepository } from "../repo/claim-repo.js";
|
|
11
|
+
import { WorkerService } from "./worker-service.js";
|
|
12
|
+
import { ClaimService } from "./claim-service.js";
|
|
13
|
+
import { OrchestratorError } from "../errors.js";
|
|
14
|
+
/**
|
|
15
|
+
* Default orchestrator configuration values.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_CONFIG = {
|
|
18
|
+
workerPoolSize: 1,
|
|
19
|
+
heartbeatIntervalSeconds: 30,
|
|
20
|
+
leaseDurationMinutes: 30,
|
|
21
|
+
reconcileIntervalSeconds: 60,
|
|
22
|
+
shutdownTimeoutSeconds: 300,
|
|
23
|
+
maxClaimRenewals: 10
|
|
24
|
+
};
|
|
25
|
+
export class OrchestratorService extends Context.Tag("OrchestratorService")() {
|
|
26
|
+
}
|
|
27
|
+
export const OrchestratorServiceLive = Layer.effect(OrchestratorService, Effect.gen(function* () {
|
|
28
|
+
const stateRepo = yield* OrchestratorStateRepository;
|
|
29
|
+
const workerService = yield* WorkerService;
|
|
30
|
+
const claimService = yield* ClaimService;
|
|
31
|
+
const taskRepo = yield* TaskRepository;
|
|
32
|
+
const claimRepo = yield* ClaimRepository;
|
|
33
|
+
return {
|
|
34
|
+
start: (config) => Effect.gen(function* () {
|
|
35
|
+
const currentState = yield* stateRepo.get();
|
|
36
|
+
// Check if already running
|
|
37
|
+
if (currentState.status === "running") {
|
|
38
|
+
return yield* Effect.fail(new OrchestratorError({
|
|
39
|
+
code: "ALREADY_RUNNING",
|
|
40
|
+
reason: "Orchestrator is already running"
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
// Check if in an incompatible state
|
|
44
|
+
if (currentState.status === "stopping") {
|
|
45
|
+
return yield* Effect.fail(new OrchestratorError({
|
|
46
|
+
code: "INVALID_STATE",
|
|
47
|
+
reason: "Orchestrator is currently stopping"
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
51
|
+
// Transition to starting
|
|
52
|
+
yield* stateRepo.update({
|
|
53
|
+
status: "starting",
|
|
54
|
+
pid: process.pid,
|
|
55
|
+
startedAt: new Date(),
|
|
56
|
+
workerPoolSize: mergedConfig.workerPoolSize,
|
|
57
|
+
reconcileIntervalSeconds: mergedConfig.reconcileIntervalSeconds,
|
|
58
|
+
heartbeatIntervalSeconds: mergedConfig.heartbeatIntervalSeconds,
|
|
59
|
+
leaseDurationMinutes: mergedConfig.leaseDurationMinutes,
|
|
60
|
+
metadata: {
|
|
61
|
+
maxClaimRenewals: mergedConfig.maxClaimRenewals,
|
|
62
|
+
shutdownTimeoutSeconds: mergedConfig.shutdownTimeoutSeconds
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
// Transition to running
|
|
66
|
+
yield* stateRepo.update({ status: "running" });
|
|
67
|
+
yield* Effect.log(`Orchestrator started with pool size ${mergedConfig.workerPoolSize}`);
|
|
68
|
+
}),
|
|
69
|
+
stop: (graceful) => Effect.gen(function* () {
|
|
70
|
+
const currentState = yield* stateRepo.get();
|
|
71
|
+
// Check if not running
|
|
72
|
+
if (currentState.status !== "running") {
|
|
73
|
+
return yield* Effect.fail(new OrchestratorError({
|
|
74
|
+
code: "NOT_RUNNING",
|
|
75
|
+
reason: "Orchestrator is not running"
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
// Transition to stopping
|
|
79
|
+
yield* stateRepo.update({ status: "stopping" });
|
|
80
|
+
yield* Effect.log("Orchestrator stopping...");
|
|
81
|
+
if (graceful) {
|
|
82
|
+
// Get all active workers
|
|
83
|
+
const workers = yield* workerService.list({
|
|
84
|
+
status: ["idle", "busy", "starting"]
|
|
85
|
+
});
|
|
86
|
+
// Signal workers to stop
|
|
87
|
+
for (const worker of workers) {
|
|
88
|
+
yield* workerService.updateStatus(worker.id, "stopping").pipe(Effect.catchAll(() => Effect.void));
|
|
89
|
+
}
|
|
90
|
+
// Note: In a full implementation, we would wait for workers
|
|
91
|
+
// to finish their current tasks with a timeout.
|
|
92
|
+
// For Phase 1, we just mark them as stopping.
|
|
93
|
+
yield* Effect.log(`Signaled ${workers.length} worker(s) to stop`);
|
|
94
|
+
}
|
|
95
|
+
// Mark any remaining active workers as dead
|
|
96
|
+
const remainingWorkers = yield* workerService.list({
|
|
97
|
+
status: ["idle", "busy", "starting", "stopping"]
|
|
98
|
+
});
|
|
99
|
+
for (const worker of remainingWorkers) {
|
|
100
|
+
yield* workerService.markDead(worker.id).pipe(Effect.catchAll(() => Effect.void));
|
|
101
|
+
}
|
|
102
|
+
// Transition to stopped
|
|
103
|
+
yield* stateRepo.update({
|
|
104
|
+
status: "stopped",
|
|
105
|
+
pid: null
|
|
106
|
+
});
|
|
107
|
+
yield* Effect.log("Orchestrator stopped");
|
|
108
|
+
}),
|
|
109
|
+
status: () => stateRepo.get(),
|
|
110
|
+
reconcile: () => Effect.gen(function* () {
|
|
111
|
+
const startTime = Date.now();
|
|
112
|
+
let deadWorkersFound = 0;
|
|
113
|
+
let expiredClaimsReleased = 0;
|
|
114
|
+
let orphanedTasksRecovered = 0;
|
|
115
|
+
let staleStatesFixed = 0;
|
|
116
|
+
// 1. Detect dead workers (missed 2+ heartbeats)
|
|
117
|
+
const deadWorkers = yield* workerService.findDead({
|
|
118
|
+
missedHeartbeats: 2
|
|
119
|
+
});
|
|
120
|
+
for (const worker of deadWorkers) {
|
|
121
|
+
yield* workerService.markDead(worker.id).pipe(Effect.catchAll(() => Effect.void));
|
|
122
|
+
// Release any claims held by this dead worker
|
|
123
|
+
yield* claimService.releaseByWorker(worker.id).pipe(Effect.catchAll(() => Effect.succeed(0)));
|
|
124
|
+
deadWorkersFound++;
|
|
125
|
+
}
|
|
126
|
+
// 2. Expire stale claims (past lease expiration)
|
|
127
|
+
const expiredClaims = yield* claimService.getExpired();
|
|
128
|
+
for (const claim of expiredClaims) {
|
|
129
|
+
yield* claimService.expire(claim.id).pipe(Effect.catchAll(() => Effect.void));
|
|
130
|
+
// Return task to ready state if it was active
|
|
131
|
+
const task = yield* taskRepo.findById(claim.taskId);
|
|
132
|
+
if (task && task.status === "active") {
|
|
133
|
+
const now = new Date();
|
|
134
|
+
yield* taskRepo.update({
|
|
135
|
+
...task,
|
|
136
|
+
status: "ready",
|
|
137
|
+
updatedAt: now
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
expiredClaimsReleased++;
|
|
141
|
+
}
|
|
142
|
+
// 3. Find orphaned tasks (status='active' but no active claim)
|
|
143
|
+
const activeTasks = yield* taskRepo.findAll({ status: "active" });
|
|
144
|
+
for (const task of activeTasks) {
|
|
145
|
+
const activeClaim = yield* claimRepo.findActiveByTaskId(task.id);
|
|
146
|
+
if (!activeClaim) {
|
|
147
|
+
// Task is orphaned - return to ready state
|
|
148
|
+
const now = new Date();
|
|
149
|
+
yield* taskRepo.update({
|
|
150
|
+
...task,
|
|
151
|
+
status: "ready",
|
|
152
|
+
updatedAt: now
|
|
153
|
+
});
|
|
154
|
+
orphanedTasksRecovered++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// 4. Fix workers marked busy but with no current_task_id
|
|
158
|
+
const busyWorkers = yield* workerService.list({ status: ["busy"] });
|
|
159
|
+
for (const worker of busyWorkers) {
|
|
160
|
+
if (worker.currentTaskId === null) {
|
|
161
|
+
yield* workerService.updateStatus(worker.id, "idle").pipe(Effect.catchAll(() => Effect.void));
|
|
162
|
+
staleStatesFixed++;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// 5. Fix workers with current_task_id but task is not active
|
|
166
|
+
for (const worker of busyWorkers) {
|
|
167
|
+
if (worker.currentTaskId) {
|
|
168
|
+
const task = yield* taskRepo.findById(worker.currentTaskId);
|
|
169
|
+
if (!task || task.status !== "active") {
|
|
170
|
+
yield* workerService.updateStatus(worker.id, "idle").pipe(Effect.catchAll(() => Effect.void));
|
|
171
|
+
staleStatesFixed++;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const reconcileTime = Date.now() - startTime;
|
|
176
|
+
// Update last reconcile timestamp
|
|
177
|
+
yield* stateRepo.update({
|
|
178
|
+
lastReconcileAt: new Date()
|
|
179
|
+
});
|
|
180
|
+
// Log if any issues were found
|
|
181
|
+
if (deadWorkersFound > 0 ||
|
|
182
|
+
expiredClaimsReleased > 0 ||
|
|
183
|
+
orphanedTasksRecovered > 0 ||
|
|
184
|
+
staleStatesFixed > 0) {
|
|
185
|
+
yield* Effect.log(`Reconciliation: ${deadWorkersFound} dead workers, ` +
|
|
186
|
+
`${expiredClaimsReleased} expired claims, ` +
|
|
187
|
+
`${orphanedTasksRecovered} orphaned tasks, ` +
|
|
188
|
+
`${staleStatesFixed} stale states fixed ` +
|
|
189
|
+
`(${reconcileTime}ms)`);
|
|
190
|
+
}
|
|
191
|
+
// Build and return the result
|
|
192
|
+
const result = {
|
|
193
|
+
deadWorkersFound,
|
|
194
|
+
expiredClaimsReleased,
|
|
195
|
+
orphanedTasksRecovered,
|
|
196
|
+
staleStatesFixed,
|
|
197
|
+
reconcileTime
|
|
198
|
+
};
|
|
199
|
+
return result;
|
|
200
|
+
})
|
|
201
|
+
};
|
|
202
|
+
}));
|
|
203
|
+
//# sourceMappingURL=orchestrator-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator-service.js","sourceRoot":"","sources":["../../src/services/orchestrator-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { CandidateNotFoundError, DatabaseError, ValidationError } from "../errors.js";
|
|
3
|
+
import { CandidateRepository } from "../repo/candidate-repo.js";
|
|
4
|
+
import { LearningService } from "./learning-service.js";
|
|
5
|
+
import { EdgeService } from "./edge-service.js";
|
|
6
|
+
import type { LearningCandidate, CandidateFilter, CandidateId, Learning } from "@jamesaphoenix/tx-types";
|
|
7
|
+
/**
|
|
8
|
+
* Result of promoting a candidate to the learnings table.
|
|
9
|
+
*/
|
|
10
|
+
export interface PromotionResult {
|
|
11
|
+
/** The updated candidate with promoted status */
|
|
12
|
+
readonly candidate: LearningCandidate;
|
|
13
|
+
/** The newly created learning */
|
|
14
|
+
readonly learning: Learning;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Result of auto-promotion batch operation.
|
|
18
|
+
*/
|
|
19
|
+
export interface AutoPromoteResult {
|
|
20
|
+
/** Number of candidates auto-promoted */
|
|
21
|
+
readonly promoted: number;
|
|
22
|
+
/** Number of candidates skipped (already processed or low confidence) */
|
|
23
|
+
readonly skipped: number;
|
|
24
|
+
/** Number of candidates that failed to promote */
|
|
25
|
+
readonly failed: number;
|
|
26
|
+
/** IDs of promoted learnings */
|
|
27
|
+
readonly learningIds: readonly number[];
|
|
28
|
+
}
|
|
29
|
+
declare const PromotionService_base: Context.TagClass<PromotionService, "PromotionService", {
|
|
30
|
+
/**
|
|
31
|
+
* List candidates matching the given filter.
|
|
32
|
+
* Supports filtering by status, confidence, category, and pagination.
|
|
33
|
+
*/
|
|
34
|
+
readonly list: (filter: CandidateFilter) => Effect.Effect<readonly LearningCandidate[], DatabaseError>;
|
|
35
|
+
/**
|
|
36
|
+
* Promote a candidate to the learnings table.
|
|
37
|
+
* Creates a new learning and updates the candidate status to 'promoted'.
|
|
38
|
+
*/
|
|
39
|
+
readonly promote: (id: CandidateId) => Effect.Effect<PromotionResult, CandidateNotFoundError | DatabaseError>;
|
|
40
|
+
/**
|
|
41
|
+
* Reject a candidate with a reason.
|
|
42
|
+
* Updates the candidate status to 'rejected' and stores the rejection reason.
|
|
43
|
+
*/
|
|
44
|
+
readonly reject: (id: CandidateId, reason: string) => Effect.Effect<LearningCandidate, CandidateNotFoundError | ValidationError | DatabaseError>;
|
|
45
|
+
/**
|
|
46
|
+
* Auto-promote high-confidence candidates.
|
|
47
|
+
* Promotes all pending candidates with 'high' confidence level.
|
|
48
|
+
* Uses 'auto' as the reviewer identifier.
|
|
49
|
+
*/
|
|
50
|
+
readonly autoPromote: () => Effect.Effect<AutoPromoteResult, DatabaseError>;
|
|
51
|
+
/**
|
|
52
|
+
* Get all pending candidates awaiting review.
|
|
53
|
+
* Convenience method equivalent to list({ status: 'pending' }).
|
|
54
|
+
*/
|
|
55
|
+
readonly getPending: () => Effect.Effect<readonly LearningCandidate[], DatabaseError>;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* PromotionService manages the lifecycle of learning candidates,
|
|
59
|
+
* including listing, promoting to learnings, rejecting, and auto-promotion.
|
|
60
|
+
*
|
|
61
|
+
* @see PRD-015 for the knowledge promotion pipeline
|
|
62
|
+
*/
|
|
63
|
+
export declare class PromotionService extends PromotionService_base {
|
|
64
|
+
}
|
|
65
|
+
export declare const PromotionServiceLive: Layer.Layer<PromotionService, never, CandidateRepository | EdgeService | LearningService>;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=promotion-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promotion-service.d.ts","sourceRoot":"","sources":["../../src/services/promotion-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,sBAAsB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,QAAQ,EACT,MAAM,yBAAyB,CAAA;AAEhC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,iBAAiB,CAAA;IACrC,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,gCAAgC;IAChC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CACxC;;IAWG;;;OAGG;mBACY,CAAC,MAAM,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,EAAE,aAAa,CAAC;IAEtG;;;OAGG;sBACe,CAAC,EAAE,EAAE,WAAW,KAAK,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,sBAAsB,GAAG,aAAa,CAAC;IAE7G;;;OAGG;qBACc,CAAC,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,sBAAsB,GAAG,eAAe,GAAG,aAAa,CAAC;IAEhJ;;;;OAIG;0BACmB,MAAM,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAE3E;;;OAGG;yBACkB,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,iBAAiB,EAAE,EAAE,aAAa,CAAC;;AAtCzF;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,qBAkCnC;CAAG;AAKN,eAAO,MAAM,oBAAoB,2FAiLhC,CAAA"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { CandidateNotFoundError, DatabaseError, ValidationError } from "../errors.js";
|
|
3
|
+
import { CandidateRepository } from "../repo/candidate-repo.js";
|
|
4
|
+
import { LearningService } from "./learning-service.js";
|
|
5
|
+
import { EdgeService } from "./edge-service.js";
|
|
6
|
+
/**
|
|
7
|
+
* PromotionService manages the lifecycle of learning candidates,
|
|
8
|
+
* including listing, promoting to learnings, rejecting, and auto-promotion.
|
|
9
|
+
*
|
|
10
|
+
* @see PRD-015 for the knowledge promotion pipeline
|
|
11
|
+
*/
|
|
12
|
+
export class PromotionService extends Context.Tag("PromotionService")() {
|
|
13
|
+
}
|
|
14
|
+
/** Duplicate detection threshold for auto-promotion (0.85 = high similarity) */
|
|
15
|
+
const DUPLICATE_MIN_SCORE = 0.85;
|
|
16
|
+
export const PromotionServiceLive = Layer.effect(PromotionService, Effect.gen(function* () {
|
|
17
|
+
const candidateRepo = yield* CandidateRepository;
|
|
18
|
+
const learningService = yield* LearningService;
|
|
19
|
+
const edgeService = yield* EdgeService;
|
|
20
|
+
/**
|
|
21
|
+
* Promote a single candidate with optional reviewer identifier.
|
|
22
|
+
* Internal helper shared by promote() and autoPromote().
|
|
23
|
+
*/
|
|
24
|
+
const promoteCandidate = (candidate, reviewedBy) => Effect.gen(function* () {
|
|
25
|
+
// Create learning from candidate content
|
|
26
|
+
// Map ValidationError to DatabaseError (validation should not fail for existing candidates)
|
|
27
|
+
const learning = yield* Effect.mapError(learningService.create({
|
|
28
|
+
content: candidate.content,
|
|
29
|
+
sourceType: "run",
|
|
30
|
+
sourceRef: candidate.sourceRunId ?? candidate.sourceFile,
|
|
31
|
+
category: candidate.category
|
|
32
|
+
}), (error) => error._tag === "ValidationError"
|
|
33
|
+
? new DatabaseError({ cause: error.reason })
|
|
34
|
+
: error);
|
|
35
|
+
// Create DERIVED_FROM edge for provenance tracking
|
|
36
|
+
// Link the learning back to its source (run or task)
|
|
37
|
+
if (candidate.sourceRunId) {
|
|
38
|
+
yield* Effect.catchAll(edgeService.createEdge({
|
|
39
|
+
edgeType: "DERIVED_FROM",
|
|
40
|
+
sourceType: "learning",
|
|
41
|
+
sourceId: String(learning.id),
|
|
42
|
+
targetType: "run",
|
|
43
|
+
targetId: candidate.sourceRunId,
|
|
44
|
+
weight: 1.0
|
|
45
|
+
}), () => Effect.void // Ignore edge creation failures
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
else if (candidate.sourceTaskId) {
|
|
49
|
+
yield* Effect.catchAll(edgeService.createEdge({
|
|
50
|
+
edgeType: "DERIVED_FROM",
|
|
51
|
+
sourceType: "learning",
|
|
52
|
+
sourceId: String(learning.id),
|
|
53
|
+
targetType: "task",
|
|
54
|
+
targetId: candidate.sourceTaskId,
|
|
55
|
+
weight: 1.0
|
|
56
|
+
}), () => Effect.void // Ignore edge creation failures
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
// Update candidate status to promoted
|
|
60
|
+
const now = new Date();
|
|
61
|
+
const updatedCandidate = yield* candidateRepo.update(candidate.id, {
|
|
62
|
+
status: "promoted",
|
|
63
|
+
reviewedAt: now,
|
|
64
|
+
reviewedBy,
|
|
65
|
+
promotedLearningId: learning.id
|
|
66
|
+
});
|
|
67
|
+
if (!updatedCandidate) {
|
|
68
|
+
return yield* Effect.fail(new CandidateNotFoundError({ id: candidate.id }));
|
|
69
|
+
}
|
|
70
|
+
return { candidate: updatedCandidate, learning };
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
list: (filter) => candidateRepo.findByFilter(filter),
|
|
74
|
+
promote: (id) => Effect.gen(function* () {
|
|
75
|
+
const candidate = yield* candidateRepo.findById(id);
|
|
76
|
+
if (!candidate) {
|
|
77
|
+
return yield* Effect.fail(new CandidateNotFoundError({ id }));
|
|
78
|
+
}
|
|
79
|
+
return yield* promoteCandidate(candidate, "manual");
|
|
80
|
+
}),
|
|
81
|
+
reject: (id, reason) => Effect.gen(function* () {
|
|
82
|
+
// Validate reason is provided
|
|
83
|
+
if (!reason || reason.trim().length === 0) {
|
|
84
|
+
return yield* Effect.fail(new ValidationError({ reason: "Rejection reason is required" }));
|
|
85
|
+
}
|
|
86
|
+
const candidate = yield* candidateRepo.findById(id);
|
|
87
|
+
if (!candidate) {
|
|
88
|
+
return yield* Effect.fail(new CandidateNotFoundError({ id }));
|
|
89
|
+
}
|
|
90
|
+
const now = new Date();
|
|
91
|
+
const updatedCandidate = yield* candidateRepo.update(id, {
|
|
92
|
+
status: "rejected",
|
|
93
|
+
reviewedAt: now,
|
|
94
|
+
reviewedBy: "manual",
|
|
95
|
+
rejectionReason: reason.trim()
|
|
96
|
+
});
|
|
97
|
+
if (!updatedCandidate) {
|
|
98
|
+
return yield* Effect.fail(new CandidateNotFoundError({ id }));
|
|
99
|
+
}
|
|
100
|
+
return updatedCandidate;
|
|
101
|
+
}),
|
|
102
|
+
autoPromote: () => Effect.gen(function* () {
|
|
103
|
+
// Get all pending high-confidence candidates
|
|
104
|
+
const candidates = yield* candidateRepo.findByFilter({
|
|
105
|
+
status: "pending",
|
|
106
|
+
confidence: "high"
|
|
107
|
+
});
|
|
108
|
+
let promoted = 0;
|
|
109
|
+
let skipped = 0;
|
|
110
|
+
let failed = 0;
|
|
111
|
+
const learningIds = [];
|
|
112
|
+
for (const candidate of candidates) {
|
|
113
|
+
// Check for duplicates using semantic search
|
|
114
|
+
const searchResult = yield* Effect.catchAll(learningService.search({
|
|
115
|
+
query: candidate.content,
|
|
116
|
+
limit: 1,
|
|
117
|
+
minScore: DUPLICATE_MIN_SCORE
|
|
118
|
+
}), () => Effect.succeed([]));
|
|
119
|
+
// If a highly similar learning exists, skip this candidate
|
|
120
|
+
if (searchResult.length > 0) {
|
|
121
|
+
skipped++;
|
|
122
|
+
// Mark as merged with the existing learning
|
|
123
|
+
yield* Effect.catchAll(candidateRepo.update(candidate.id, {
|
|
124
|
+
status: "merged",
|
|
125
|
+
reviewedAt: new Date(),
|
|
126
|
+
reviewedBy: "auto",
|
|
127
|
+
promotedLearningId: searchResult[0].id
|
|
128
|
+
}), () => Effect.void);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
// Promote the candidate
|
|
132
|
+
const result = yield* Effect.either(promoteCandidate(candidate, "auto"));
|
|
133
|
+
if (result._tag === "Right") {
|
|
134
|
+
promoted++;
|
|
135
|
+
learningIds.push(result.right.learning.id);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
failed++;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
promoted,
|
|
143
|
+
skipped,
|
|
144
|
+
failed,
|
|
145
|
+
learningIds
|
|
146
|
+
};
|
|
147
|
+
}),
|
|
148
|
+
getPending: () => candidateRepo.findByFilter({ status: "pending" })
|
|
149
|
+
};
|
|
150
|
+
}));
|
|
151
|
+
//# sourceMappingURL=promotion-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promotion-service.js","sourceRoot":"","sources":["../../src/services/promotion-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
declare const QueryExpansionUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
3
|
+
readonly _tag: "QueryExpansionUnavailableError";
|
|
4
|
+
} & Readonly<A>;
|
|
5
|
+
/**
|
|
6
|
+
* Error indicating query expansion is unavailable.
|
|
7
|
+
*/
|
|
8
|
+
export declare class QueryExpansionUnavailableError extends QueryExpansionUnavailableError_base<{
|
|
9
|
+
readonly reason: string;
|
|
10
|
+
}> {
|
|
11
|
+
get message(): string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Result of query expansion.
|
|
15
|
+
*/
|
|
16
|
+
export interface QueryExpansionResult {
|
|
17
|
+
/** Original query */
|
|
18
|
+
readonly original: string;
|
|
19
|
+
/** Expanded queries (includes original plus alternatives) */
|
|
20
|
+
readonly expanded: readonly string[];
|
|
21
|
+
/** Whether expansion was performed (false if using noop) */
|
|
22
|
+
readonly wasExpanded: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare const QueryExpansionService_base: Context.TagClass<QueryExpansionService, "QueryExpansionService", {
|
|
25
|
+
/** Expand a search query into multiple alternative phrasings */
|
|
26
|
+
readonly expand: (query: string) => Effect.Effect<QueryExpansionResult, QueryExpansionUnavailableError>;
|
|
27
|
+
/** Check if query expansion is available */
|
|
28
|
+
readonly isAvailable: () => Effect.Effect<boolean>;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* QueryExpansionService uses an LLM to generate alternative phrasings of search queries.
|
|
32
|
+
* This improves recall by searching for semantically equivalent but differently worded queries.
|
|
33
|
+
*
|
|
34
|
+
* Design: Following DD-006 patterns for LLM integration.
|
|
35
|
+
* The service gracefully degrades when ANTHROPIC_API_KEY is not set.
|
|
36
|
+
*/
|
|
37
|
+
export declare class QueryExpansionService extends QueryExpansionService_base {
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Noop implementation - returns original query only.
|
|
41
|
+
* Used when ANTHROPIC_API_KEY is not set or LLM features are disabled.
|
|
42
|
+
*/
|
|
43
|
+
export declare const QueryExpansionServiceNoop: Layer.Layer<QueryExpansionService, never, never>;
|
|
44
|
+
/**
|
|
45
|
+
* Live implementation using Anthropic Claude API.
|
|
46
|
+
* Lazy-loads the SDK and caches the client.
|
|
47
|
+
*/
|
|
48
|
+
export declare const QueryExpansionServiceLive: Layer.Layer<QueryExpansionService, QueryExpansionUnavailableError, never>;
|
|
49
|
+
/**
|
|
50
|
+
* Auto-detecting layer that uses Live if ANTHROPIC_API_KEY is set, Noop otherwise.
|
|
51
|
+
* This allows graceful degradation when the API key is not configured.
|
|
52
|
+
*/
|
|
53
|
+
export declare const QueryExpansionServiceAuto: Layer.Layer<QueryExpansionService, QueryExpansionUnavailableError, never>;
|
|
54
|
+
export {};
|
|
55
|
+
//# sourceMappingURL=query-expansion-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-expansion-service.d.ts","sourceRoot":"","sources":["../../src/services/query-expansion-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,QAAQ,CAAA;;;;AAG/D;;GAEG;AACH,qBAAa,8BAA+B,SAAQ,oCAAmD;IACrG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,CAAC;IACA,IAAI,OAAO,WAEV;CACF;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qBAAqB;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;CAC9B;;IA2BG,gEAAgE;qBAC/C,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,8BAA8B,CAAC;IACvG,4CAA4C;0BACtB,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;AAbtD;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,0BAQxC;CAAG;AAyDN;;;GAGG;AACH,eAAO,MAAM,yBAAyB,kDAUrC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,2EAmFrC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,2EAUrC,CAAA"}
|