@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,522 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { DaemonError } from "../errors.js";
|
|
7
|
+
/**
|
|
8
|
+
* Default path for the daemon PID file.
|
|
9
|
+
*/
|
|
10
|
+
export const PID_FILE_PATH = ".tx/daemon.pid";
|
|
11
|
+
/**
|
|
12
|
+
* Default install path for the launchd plist file.
|
|
13
|
+
* Located in the user's LaunchAgents directory for per-user daemons.
|
|
14
|
+
*/
|
|
15
|
+
export const LAUNCHD_PLIST_PATH = "~/Library/LaunchAgents/com.tx.daemon.plist";
|
|
16
|
+
/**
|
|
17
|
+
* Default install path for the systemd service file.
|
|
18
|
+
* Located in the user's systemd user directory for per-user services.
|
|
19
|
+
*/
|
|
20
|
+
export const SYSTEMD_SERVICE_PATH = "~/.config/systemd/user/tx-daemon.service";
|
|
21
|
+
/**
|
|
22
|
+
* Generate a macOS launchd plist file content.
|
|
23
|
+
* Creates a valid XML plist that can be used with launchctl to run the daemon.
|
|
24
|
+
*
|
|
25
|
+
* The generated plist configures the daemon to:
|
|
26
|
+
* - Run at load (start when user logs in)
|
|
27
|
+
* - Keep alive (restart if it crashes)
|
|
28
|
+
* - Log stdout and stderr to the specified log path
|
|
29
|
+
*
|
|
30
|
+
* @param options - Configuration options for the plist
|
|
31
|
+
* @returns The XML content for the launchd plist file
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const plist = generateLaunchdPlist({
|
|
36
|
+
* label: "com.tx.daemon",
|
|
37
|
+
* executablePath: "/usr/local/bin/tx",
|
|
38
|
+
* logPath: "~/Library/Logs/tx-daemon.log"
|
|
39
|
+
* })
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export const generateLaunchdPlist = (options) => {
|
|
43
|
+
const { label, executablePath, logPath } = options;
|
|
44
|
+
// Expand ~ to home directory for the log path
|
|
45
|
+
const resolvedLogPath = logPath
|
|
46
|
+
? logPath.replace(/^~/, homedir())
|
|
47
|
+
: join(homedir(), "Library", "Logs", "tx-daemon.log");
|
|
48
|
+
// Generate valid XML plist
|
|
49
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
50
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
51
|
+
<plist version="1.0">
|
|
52
|
+
<dict>
|
|
53
|
+
<key>Label</key>
|
|
54
|
+
<string>${escapeXml(label)}</string>
|
|
55
|
+
<key>ProgramArguments</key>
|
|
56
|
+
<array>
|
|
57
|
+
<string>${escapeXml(executablePath)}</string>
|
|
58
|
+
<string>daemon</string>
|
|
59
|
+
<string>run</string>
|
|
60
|
+
</array>
|
|
61
|
+
<key>RunAtLoad</key>
|
|
62
|
+
<true/>
|
|
63
|
+
<key>KeepAlive</key>
|
|
64
|
+
<true/>
|
|
65
|
+
<key>StandardOutPath</key>
|
|
66
|
+
<string>${escapeXml(resolvedLogPath)}</string>
|
|
67
|
+
<key>StandardErrorPath</key>
|
|
68
|
+
<string>${escapeXml(resolvedLogPath)}</string>
|
|
69
|
+
</dict>
|
|
70
|
+
</plist>
|
|
71
|
+
`;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Escape special characters for XML content.
|
|
75
|
+
*/
|
|
76
|
+
const escapeXml = (str) => str
|
|
77
|
+
.replace(/&/g, "&")
|
|
78
|
+
.replace(/</g, "<")
|
|
79
|
+
.replace(/>/g, ">")
|
|
80
|
+
.replace(/"/g, """)
|
|
81
|
+
.replace(/'/g, "'");
|
|
82
|
+
/**
|
|
83
|
+
* Generate a Linux systemd service file content.
|
|
84
|
+
* Creates a valid systemd unit file for a user service.
|
|
85
|
+
*
|
|
86
|
+
* The generated service file configures the daemon to:
|
|
87
|
+
* - Start after the network is available
|
|
88
|
+
* - Run as Type=simple (foreground process)
|
|
89
|
+
* - Restart always on failure with 5 second delay
|
|
90
|
+
* - Be enabled for multi-user target
|
|
91
|
+
*
|
|
92
|
+
* @param options - Configuration options for the service file
|
|
93
|
+
* @returns The content for the systemd service file
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const service = generateSystemdService({
|
|
98
|
+
* executablePath: "/usr/local/bin/tx",
|
|
99
|
+
* user: "myuser"
|
|
100
|
+
* })
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const generateSystemdService = (options) => {
|
|
104
|
+
const { executablePath, user } = options;
|
|
105
|
+
// Build the [Service] section lines
|
|
106
|
+
const serviceLines = [
|
|
107
|
+
"Type=simple",
|
|
108
|
+
`ExecStart=${executablePath} daemon run`,
|
|
109
|
+
"Restart=always",
|
|
110
|
+
"RestartSec=5"
|
|
111
|
+
];
|
|
112
|
+
// Add User= directive only if user is provided
|
|
113
|
+
if (user) {
|
|
114
|
+
serviceLines.push(`User=${user}`);
|
|
115
|
+
}
|
|
116
|
+
return `[Unit]
|
|
117
|
+
Description=tx Daemon - Task and memory management for AI agents
|
|
118
|
+
After=network.target
|
|
119
|
+
|
|
120
|
+
[Service]
|
|
121
|
+
${serviceLines.join("\n")}
|
|
122
|
+
|
|
123
|
+
[Install]
|
|
124
|
+
WantedBy=default.target
|
|
125
|
+
`;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* DaemonService manages the lifecycle of the tx daemon process.
|
|
129
|
+
* The daemon runs in the background and provides:
|
|
130
|
+
* - File watching for auto-sync
|
|
131
|
+
* - JSONL promotion on git operations
|
|
132
|
+
* - Background task processing
|
|
133
|
+
*
|
|
134
|
+
* See DD-015 and PRD-015 for full specification.
|
|
135
|
+
*/
|
|
136
|
+
export class DaemonService extends Context.Tag("DaemonService")() {
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Check if a process with the given PID is currently running.
|
|
140
|
+
* Uses kill signal 0 which doesn't actually send a signal but checks if the process exists.
|
|
141
|
+
*
|
|
142
|
+
* @param pid - The process ID to check
|
|
143
|
+
* @returns Effect that resolves to true if the process is running, false otherwise
|
|
144
|
+
*/
|
|
145
|
+
export const isProcessRunning = (pid) => Effect.try({
|
|
146
|
+
try: () => {
|
|
147
|
+
// Signal 0 doesn't send anything but checks if process exists
|
|
148
|
+
process.kill(pid, 0);
|
|
149
|
+
return true;
|
|
150
|
+
},
|
|
151
|
+
catch: (error) => error
|
|
152
|
+
}).pipe(Effect.catchAll((error) => {
|
|
153
|
+
// ESRCH means no such process - return false (not running) as success value
|
|
154
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
155
|
+
return Effect.succeed(false);
|
|
156
|
+
}
|
|
157
|
+
// EPERM means process exists but we don't have permission to signal it
|
|
158
|
+
// The process is still running, just owned by another user - return true as success value
|
|
159
|
+
if (error instanceof Error && "code" in error && error.code === "EPERM") {
|
|
160
|
+
return Effect.succeed(true);
|
|
161
|
+
}
|
|
162
|
+
// Any other error is unexpected - convert to DaemonError
|
|
163
|
+
return Effect.fail(new DaemonError({
|
|
164
|
+
code: "PROCESS_CHECK_FAILED",
|
|
165
|
+
message: `Failed to check if process ${pid} is running: ${error}`,
|
|
166
|
+
pid
|
|
167
|
+
}));
|
|
168
|
+
}));
|
|
169
|
+
/**
|
|
170
|
+
* Write a PID to the daemon PID file.
|
|
171
|
+
* Creates the .tx directory if it doesn't exist.
|
|
172
|
+
*
|
|
173
|
+
* @param pid - The process ID to write
|
|
174
|
+
* @returns Effect that resolves to void on success
|
|
175
|
+
*/
|
|
176
|
+
export const writePid = (pid) => Effect.try({
|
|
177
|
+
try: () => {
|
|
178
|
+
const dir = dirname(PID_FILE_PATH);
|
|
179
|
+
if (!existsSync(dir)) {
|
|
180
|
+
mkdirSync(dir, { recursive: true });
|
|
181
|
+
}
|
|
182
|
+
writeFileSync(PID_FILE_PATH, String(pid), "utf-8");
|
|
183
|
+
},
|
|
184
|
+
catch: (error) => new DaemonError({
|
|
185
|
+
code: "PID_WRITE_FAILED",
|
|
186
|
+
message: `Failed to write PID file: ${error}`,
|
|
187
|
+
pid
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
/**
|
|
191
|
+
* Read the PID from the daemon PID file.
|
|
192
|
+
* Returns null if the file doesn't exist.
|
|
193
|
+
* Handles stale PID cleanup: if the PID file exists but the process is not running,
|
|
194
|
+
* the stale PID file is automatically removed and null is returned.
|
|
195
|
+
*
|
|
196
|
+
* @returns Effect that resolves to the PID number, or null if no valid PID file exists
|
|
197
|
+
*/
|
|
198
|
+
export const readPid = () => Effect.gen(function* () {
|
|
199
|
+
// Check if file exists
|
|
200
|
+
if (!existsSync(PID_FILE_PATH)) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
// Read the PID file
|
|
204
|
+
const content = yield* Effect.try({
|
|
205
|
+
try: () => readFileSync(PID_FILE_PATH, "utf-8").trim(),
|
|
206
|
+
catch: (error) => new DaemonError({
|
|
207
|
+
code: "PID_READ_FAILED",
|
|
208
|
+
message: `Failed to read PID file: ${error}`,
|
|
209
|
+
pid: null
|
|
210
|
+
})
|
|
211
|
+
});
|
|
212
|
+
// Parse the PID
|
|
213
|
+
const pid = parseInt(content, 10);
|
|
214
|
+
if (isNaN(pid) || pid <= 0) {
|
|
215
|
+
// Invalid PID content, remove the stale file
|
|
216
|
+
yield* removePid();
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
// Check if the process is still running
|
|
220
|
+
const running = yield* isProcessRunning(pid);
|
|
221
|
+
if (!running) {
|
|
222
|
+
// Process is not running, remove the stale PID file
|
|
223
|
+
yield* removePid();
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
return pid;
|
|
227
|
+
});
|
|
228
|
+
/**
|
|
229
|
+
* Remove the daemon PID file.
|
|
230
|
+
* Does nothing if the file doesn't exist.
|
|
231
|
+
*
|
|
232
|
+
* @returns Effect that resolves to void on success
|
|
233
|
+
*/
|
|
234
|
+
export const removePid = () => Effect.try({
|
|
235
|
+
try: () => {
|
|
236
|
+
if (existsSync(PID_FILE_PATH)) {
|
|
237
|
+
unlinkSync(PID_FILE_PATH);
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
catch: (error) => new DaemonError({
|
|
241
|
+
code: "PID_REMOVE_FAILED",
|
|
242
|
+
message: `Failed to remove PID file: ${error}`,
|
|
243
|
+
pid: null
|
|
244
|
+
})
|
|
245
|
+
});
|
|
246
|
+
/**
|
|
247
|
+
* Path to store the daemon start timestamp for uptime calculation.
|
|
248
|
+
*/
|
|
249
|
+
const STARTED_AT_PATH = ".tx/daemon.started";
|
|
250
|
+
/**
|
|
251
|
+
* Write the daemon start timestamp to a file.
|
|
252
|
+
*/
|
|
253
|
+
const writeStartedAt = (date) => Effect.try({
|
|
254
|
+
try: () => {
|
|
255
|
+
const dir = dirname(STARTED_AT_PATH);
|
|
256
|
+
if (!existsSync(dir)) {
|
|
257
|
+
mkdirSync(dir, { recursive: true });
|
|
258
|
+
}
|
|
259
|
+
writeFileSync(STARTED_AT_PATH, date.toISOString(), "utf-8");
|
|
260
|
+
},
|
|
261
|
+
catch: (error) => new DaemonError({
|
|
262
|
+
code: "STARTED_AT_WRITE_FAILED",
|
|
263
|
+
message: `Failed to write started_at file: ${error}`,
|
|
264
|
+
pid: null
|
|
265
|
+
})
|
|
266
|
+
});
|
|
267
|
+
/**
|
|
268
|
+
* Read the daemon start timestamp from file.
|
|
269
|
+
*/
|
|
270
|
+
const readStartedAt = () => Effect.try({
|
|
271
|
+
try: () => {
|
|
272
|
+
if (!existsSync(STARTED_AT_PATH)) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
const content = readFileSync(STARTED_AT_PATH, "utf-8").trim();
|
|
276
|
+
const date = new Date(content);
|
|
277
|
+
return isNaN(date.getTime()) ? null : date;
|
|
278
|
+
},
|
|
279
|
+
catch: (error) => new DaemonError({
|
|
280
|
+
code: "STARTED_AT_READ_FAILED",
|
|
281
|
+
message: `Failed to read started_at file: ${error}`,
|
|
282
|
+
pid: null
|
|
283
|
+
})
|
|
284
|
+
});
|
|
285
|
+
/**
|
|
286
|
+
* Remove the daemon start timestamp file.
|
|
287
|
+
*/
|
|
288
|
+
const removeStartedAt = () => Effect.try({
|
|
289
|
+
try: () => {
|
|
290
|
+
if (existsSync(STARTED_AT_PATH)) {
|
|
291
|
+
unlinkSync(STARTED_AT_PATH);
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
catch: (error) => new DaemonError({
|
|
295
|
+
code: "STARTED_AT_REMOVE_FAILED",
|
|
296
|
+
message: `Failed to remove started_at file: ${error}`,
|
|
297
|
+
pid: null
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
/**
|
|
301
|
+
* Send a signal to a process by PID.
|
|
302
|
+
* Returns true if the signal was sent successfully, false if the process doesn't exist.
|
|
303
|
+
*/
|
|
304
|
+
const sendSignal = (pid, signal) => Effect.try({
|
|
305
|
+
try: () => {
|
|
306
|
+
process.kill(pid, signal);
|
|
307
|
+
return true;
|
|
308
|
+
},
|
|
309
|
+
catch: (error) => error
|
|
310
|
+
}).pipe(Effect.catchAll((error) => {
|
|
311
|
+
// ESRCH means no such process - return false (not running) as success value
|
|
312
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
313
|
+
return Effect.succeed(false);
|
|
314
|
+
}
|
|
315
|
+
// Any other error is unexpected - convert to DaemonError
|
|
316
|
+
return Effect.fail(new DaemonError({
|
|
317
|
+
code: "SIGNAL_FAILED",
|
|
318
|
+
message: `Failed to send signal ${signal} to process ${pid}: ${error}`,
|
|
319
|
+
pid
|
|
320
|
+
}));
|
|
321
|
+
}));
|
|
322
|
+
/**
|
|
323
|
+
* Wait for a process to exit with a timeout.
|
|
324
|
+
* Returns true if the process exited, false if timeout was reached.
|
|
325
|
+
*/
|
|
326
|
+
const waitForExit = (pid, timeoutMs) => Effect.gen(function* () {
|
|
327
|
+
const startTime = Date.now();
|
|
328
|
+
const pollIntervalMs = 100;
|
|
329
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
330
|
+
const running = yield* isProcessRunning(pid);
|
|
331
|
+
if (!running) {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
yield* Effect.sleep(`${pollIntervalMs} millis`);
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
});
|
|
338
|
+
/**
|
|
339
|
+
* Default daemon configuration.
|
|
340
|
+
*/
|
|
341
|
+
export const defaultDaemonConfig = {
|
|
342
|
+
command: "tx",
|
|
343
|
+
args: ["daemon", "run"]
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* Spawn a daemon process and wait for it to either start successfully or fail.
|
|
347
|
+
* This properly handles the async ENOENT error that spawn emits.
|
|
348
|
+
*/
|
|
349
|
+
const spawnDaemonProcess = (config) => new Promise((resolve, reject) => {
|
|
350
|
+
const spawnedProcess = spawn(config.command, [...config.args], {
|
|
351
|
+
detached: true,
|
|
352
|
+
stdio: "ignore",
|
|
353
|
+
cwd: config.cwd ?? process.cwd(),
|
|
354
|
+
env: config.env ?? process.env
|
|
355
|
+
});
|
|
356
|
+
// Handle spawn errors (like ENOENT when command doesn't exist)
|
|
357
|
+
spawnedProcess.on("error", (error) => {
|
|
358
|
+
if (error.code === "ENOENT") {
|
|
359
|
+
reject(new DaemonError({
|
|
360
|
+
code: "COMMAND_NOT_FOUND",
|
|
361
|
+
message: `Command '${config.command}' not found. Make sure it is installed and in PATH.`,
|
|
362
|
+
pid: null
|
|
363
|
+
}));
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
reject(new DaemonError({
|
|
367
|
+
code: "SPAWN_FAILED",
|
|
368
|
+
message: `Failed to spawn daemon process: ${error.message}`,
|
|
369
|
+
pid: null
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
// Check if we got a PID (spawn succeeded synchronously)
|
|
374
|
+
if (spawnedProcess.pid !== undefined) {
|
|
375
|
+
// Unref to allow parent to exit independently
|
|
376
|
+
spawnedProcess.unref();
|
|
377
|
+
resolve({ child: spawnedProcess, pid: spawnedProcess.pid });
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
// Wait a tick for the error event to fire
|
|
381
|
+
setImmediate(() => {
|
|
382
|
+
if (spawnedProcess.pid !== undefined) {
|
|
383
|
+
spawnedProcess.unref();
|
|
384
|
+
resolve({ child: spawnedProcess, pid: spawnedProcess.pid });
|
|
385
|
+
}
|
|
386
|
+
// If still no PID, the error handler will reject
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
/**
|
|
391
|
+
* Internal start implementation for the daemon.
|
|
392
|
+
* Extracted to allow reuse in restart without circular dependency.
|
|
393
|
+
*/
|
|
394
|
+
const startDaemonImpl = (config) => Effect.gen(function* () {
|
|
395
|
+
// Check if daemon is already running
|
|
396
|
+
const existingPid = yield* readPid();
|
|
397
|
+
if (existingPid !== null) {
|
|
398
|
+
return yield* Effect.fail(new DaemonError({
|
|
399
|
+
code: "ALREADY_RUNNING",
|
|
400
|
+
message: `Daemon is already running with PID ${existingPid}`,
|
|
401
|
+
pid: existingPid
|
|
402
|
+
}));
|
|
403
|
+
}
|
|
404
|
+
// Spawn the daemon process with proper error handling
|
|
405
|
+
const { pid } = yield* Effect.tryPromise({
|
|
406
|
+
try: () => spawnDaemonProcess(config),
|
|
407
|
+
catch: (error) => {
|
|
408
|
+
if (error instanceof DaemonError) {
|
|
409
|
+
return error;
|
|
410
|
+
}
|
|
411
|
+
return new DaemonError({
|
|
412
|
+
code: "SPAWN_FAILED",
|
|
413
|
+
message: `Failed to spawn daemon process: ${error}`,
|
|
414
|
+
pid: null
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
// Write PID file
|
|
419
|
+
yield* writePid(pid);
|
|
420
|
+
// Write started timestamp
|
|
421
|
+
yield* writeStartedAt(new Date());
|
|
422
|
+
// Wait a short time and verify process is still running
|
|
423
|
+
yield* Effect.sleep("100 millis");
|
|
424
|
+
const running = yield* isProcessRunning(pid);
|
|
425
|
+
if (!running) {
|
|
426
|
+
// Process died immediately, clean up
|
|
427
|
+
yield* removePid();
|
|
428
|
+
yield* removeStartedAt();
|
|
429
|
+
return yield* Effect.fail(new DaemonError({
|
|
430
|
+
code: "PROCESS_DIED",
|
|
431
|
+
message: "Daemon process exited immediately after starting",
|
|
432
|
+
pid
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
/**
|
|
437
|
+
* Internal stop implementation for the daemon.
|
|
438
|
+
* Extracted to allow reuse in restart without circular dependency.
|
|
439
|
+
*/
|
|
440
|
+
const stopDaemonImpl = () => Effect.gen(function* () {
|
|
441
|
+
// Read PID from file
|
|
442
|
+
const pid = yield* readPid();
|
|
443
|
+
if (pid === null) {
|
|
444
|
+
// No daemon running (readPid handles stale cleanup)
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
// Send SIGTERM
|
|
448
|
+
const termSent = yield* sendSignal(pid, "SIGTERM");
|
|
449
|
+
if (!termSent) {
|
|
450
|
+
// Process already gone, clean up files
|
|
451
|
+
yield* removePid();
|
|
452
|
+
yield* removeStartedAt();
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
// Wait for process to exit (timeout 10s)
|
|
456
|
+
const exited = yield* waitForExit(pid, 10000);
|
|
457
|
+
if (!exited) {
|
|
458
|
+
// Process didn't exit gracefully, send SIGKILL
|
|
459
|
+
yield* sendSignal(pid, "SIGKILL");
|
|
460
|
+
// Wait a bit more for SIGKILL to take effect
|
|
461
|
+
yield* waitForExit(pid, 1000);
|
|
462
|
+
}
|
|
463
|
+
// Clean up files
|
|
464
|
+
yield* removePid();
|
|
465
|
+
yield* removeStartedAt();
|
|
466
|
+
});
|
|
467
|
+
/**
|
|
468
|
+
* Internal status implementation for the daemon.
|
|
469
|
+
*/
|
|
470
|
+
const statusDaemonImpl = () => Effect.gen(function* () {
|
|
471
|
+
const pid = yield* readPid();
|
|
472
|
+
if (pid === null) {
|
|
473
|
+
return {
|
|
474
|
+
running: false,
|
|
475
|
+
pid: null,
|
|
476
|
+
uptime: null,
|
|
477
|
+
startedAt: null
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
// Process is running (readPid already verified this)
|
|
481
|
+
const startedAt = yield* readStartedAt();
|
|
482
|
+
const uptime = startedAt ? Date.now() - startedAt.getTime() : null;
|
|
483
|
+
return {
|
|
484
|
+
running: true,
|
|
485
|
+
pid,
|
|
486
|
+
uptime,
|
|
487
|
+
startedAt
|
|
488
|
+
};
|
|
489
|
+
});
|
|
490
|
+
/**
|
|
491
|
+
* DaemonServiceLive implementation that manages a real daemon process.
|
|
492
|
+
* Uses child_process.spawn with detached:true to fork the daemon.
|
|
493
|
+
*/
|
|
494
|
+
export const DaemonServiceLive = Layer.succeed(DaemonService, {
|
|
495
|
+
start: () => startDaemonImpl(defaultDaemonConfig),
|
|
496
|
+
stop: () => stopDaemonImpl(),
|
|
497
|
+
status: () => statusDaemonImpl(),
|
|
498
|
+
restart: () => Effect.gen(function* () {
|
|
499
|
+
// Stop if running
|
|
500
|
+
yield* stopDaemonImpl();
|
|
501
|
+
// Small delay before starting again
|
|
502
|
+
yield* Effect.sleep("200 millis");
|
|
503
|
+
// Start fresh
|
|
504
|
+
yield* startDaemonImpl(defaultDaemonConfig);
|
|
505
|
+
})
|
|
506
|
+
});
|
|
507
|
+
/**
|
|
508
|
+
* DaemonServiceNoop - no-op implementation for testing.
|
|
509
|
+
* All operations succeed but don't actually manage a process.
|
|
510
|
+
*/
|
|
511
|
+
export const DaemonServiceNoop = Layer.succeed(DaemonService, {
|
|
512
|
+
start: () => Effect.void,
|
|
513
|
+
stop: () => Effect.void,
|
|
514
|
+
status: () => Effect.succeed({
|
|
515
|
+
running: false,
|
|
516
|
+
pid: null,
|
|
517
|
+
uptime: null,
|
|
518
|
+
startedAt: null
|
|
519
|
+
}),
|
|
520
|
+
restart: () => Effect.void
|
|
521
|
+
});
|
|
522
|
+
//# sourceMappingURL=daemon-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-service.js","sourceRoot":"","sources":["../../src/services/daemon-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { DeduplicationRepository } from "../repo/deduplication-repo.js";
|
|
3
|
+
import { DatabaseError } from "../errors.js";
|
|
4
|
+
import type { FileProgress, LineProcessResult, FileProcessResult, DeduplicationOptions } from "@jamesaphoenix/tx-types";
|
|
5
|
+
declare const DeduplicationService_base: Context.TagClass<DeduplicationService, "DeduplicationService", {
|
|
6
|
+
/**
|
|
7
|
+
* Process a single JSONL line and return deduplication result.
|
|
8
|
+
* Returns isNew=true if this is a newly seen line (hash recorded).
|
|
9
|
+
* Returns isNew=false if we've already processed this content.
|
|
10
|
+
*/
|
|
11
|
+
readonly processLine: (content: string, filePath: string, lineNumber: number) => Effect.Effect<LineProcessResult, DatabaseError>;
|
|
12
|
+
/**
|
|
13
|
+
* Process multiple JSONL lines with batch hash checking.
|
|
14
|
+
* More efficient than calling processLine repeatedly.
|
|
15
|
+
*/
|
|
16
|
+
readonly processLines: (lines: readonly {
|
|
17
|
+
content: string;
|
|
18
|
+
lineNumber: number;
|
|
19
|
+
}[], filePath: string, options?: DeduplicationOptions) => Effect.Effect<FileProcessResult, DatabaseError>;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a content hash has already been processed.
|
|
22
|
+
*/
|
|
23
|
+
readonly isProcessed: (content: string) => Effect.Effect<boolean, DatabaseError>;
|
|
24
|
+
/**
|
|
25
|
+
* Check multiple content strings at once.
|
|
26
|
+
* Returns the set of content strings that have been processed.
|
|
27
|
+
*/
|
|
28
|
+
readonly filterProcessed: (contents: readonly string[]) => Effect.Effect<Set<string>, DatabaseError>;
|
|
29
|
+
/**
|
|
30
|
+
* Get processing progress for a file.
|
|
31
|
+
* Returns null if file has never been processed.
|
|
32
|
+
*/
|
|
33
|
+
readonly getProgress: (filePath: string) => Effect.Effect<FileProgress | null, DatabaseError>;
|
|
34
|
+
/**
|
|
35
|
+
* Update processing progress for a file.
|
|
36
|
+
*/
|
|
37
|
+
readonly updateProgress: (filePath: string, lastLineProcessed: number, lastByteOffset: number, fileSize?: number, fileChecksum?: string) => Effect.Effect<FileProgress, DatabaseError>;
|
|
38
|
+
/**
|
|
39
|
+
* Reset progress for a file (for reprocessing).
|
|
40
|
+
* Also clears all recorded hashes from this file.
|
|
41
|
+
*/
|
|
42
|
+
readonly resetFile: (filePath: string) => Effect.Effect<{
|
|
43
|
+
hashesDeleted: number;
|
|
44
|
+
}, DatabaseError>;
|
|
45
|
+
/**
|
|
46
|
+
* Get statistics about processed content.
|
|
47
|
+
*/
|
|
48
|
+
readonly getStats: () => Effect.Effect<{
|
|
49
|
+
totalHashes: number;
|
|
50
|
+
trackedFiles: number;
|
|
51
|
+
}, DatabaseError>;
|
|
52
|
+
/**
|
|
53
|
+
* Compute SHA256 hash of content.
|
|
54
|
+
* Exposed for use by callers who need to pre-compute hashes.
|
|
55
|
+
*/
|
|
56
|
+
readonly computeHash: (content: string) => string;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* DeduplicationService handles JSONL line deduplication via SHA256 hashing.
|
|
60
|
+
* Tracks processed content hashes to skip already-seen lines.
|
|
61
|
+
* Supports incremental processing by tracking file progress.
|
|
62
|
+
*/
|
|
63
|
+
export declare class DeduplicationService extends DeduplicationService_base {
|
|
64
|
+
}
|
|
65
|
+
export declare const DeduplicationServiceLive: Layer.Layer<DeduplicationService, never, DeduplicationRepository>;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=deduplication-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deduplication-service.d.ts","sourceRoot":"","sources":["../../src/services/deduplication-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AAEvE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,yBAAyB,CAAA;;IAgB5B;;;;OAIG;0BACmB,CACpB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAEpD;;;OAGG;2BACoB,CACrB,KAAK,EAAE,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,EACzD,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,oBAAoB,KAC3B,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAEpD;;OAEG;0BACmB,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC;IAEhF;;;OAGG;8BACuB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAEpG;;;OAGG;0BACmB,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,EAAE,aAAa,CAAC;IAE7F;;OAEG;6BACsB,CACvB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,KAClB,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC;IAE/C;;;OAGG;wBACiB,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,EAAE,aAAa,CAAC;IAEjG;;OAEG;uBACgB,MAAM,MAAM,CAAC,MAAM,CAAC;QACrC,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;KACrB,EAAE,aAAa,CAAC;IAEjB;;;OAGG;0BACmB,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM;;AA3ErD;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,yBAwEvC;CAAG;AAEN,eAAO,MAAM,wBAAwB,mEAgKpC,CAAA"}
|