@orkify/cli 1.0.0-beta.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/LICENSE +191 -0
- package/README.md +1701 -0
- package/bin/orkify +3 -0
- package/boot/systemd/orkify@.service +30 -0
- package/dist/agent-name.d.ts +4 -0
- package/dist/agent-name.js +42 -0
- package/dist/alerts/AlertEvaluator.d.ts +14 -0
- package/dist/alerts/AlertEvaluator.js +135 -0
- package/dist/cli/commands/autostart.d.ts +3 -0
- package/dist/cli/commands/autostart.js +11 -0
- package/dist/cli/commands/crash-test.d.ts +3 -0
- package/dist/cli/commands/crash-test.js +17 -0
- package/dist/cli/commands/daemon-reload.d.ts +3 -0
- package/dist/cli/commands/daemon-reload.js +72 -0
- package/dist/cli/commands/delete.d.ts +3 -0
- package/dist/cli/commands/delete.js +37 -0
- package/dist/cli/commands/deploy.d.ts +6 -0
- package/dist/cli/commands/deploy.js +266 -0
- package/dist/cli/commands/down.d.ts +3 -0
- package/dist/cli/commands/down.js +36 -0
- package/dist/cli/commands/flush.d.ts +3 -0
- package/dist/cli/commands/flush.js +28 -0
- package/dist/cli/commands/kill.d.ts +3 -0
- package/dist/cli/commands/kill.js +35 -0
- package/dist/cli/commands/list.d.ts +14 -0
- package/dist/cli/commands/list.js +361 -0
- package/dist/cli/commands/logs.d.ts +3 -0
- package/dist/cli/commands/logs.js +107 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.js +151 -0
- package/dist/cli/commands/reload.d.ts +3 -0
- package/dist/cli/commands/reload.js +54 -0
- package/dist/cli/commands/restart.d.ts +3 -0
- package/dist/cli/commands/restart.js +43 -0
- package/dist/cli/commands/restore.d.ts +3 -0
- package/dist/cli/commands/restore.js +88 -0
- package/dist/cli/commands/run.d.ts +8 -0
- package/dist/cli/commands/run.js +212 -0
- package/dist/cli/commands/snap.d.ts +3 -0
- package/dist/cli/commands/snap.js +30 -0
- package/dist/cli/commands/up.d.ts +3 -0
- package/dist/cli/commands/up.js +125 -0
- package/dist/cli/crash-recovery.d.ts +2 -0
- package/dist/cli/crash-recovery.js +67 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +46 -0
- package/dist/cli/parse.d.ts +28 -0
- package/dist/cli/parse.js +97 -0
- package/dist/cluster/ClusterWrapper.d.ts +18 -0
- package/dist/cluster/ClusterWrapper.js +602 -0
- package/dist/config/ConfigStore.d.ts +11 -0
- package/dist/config/ConfigStore.js +21 -0
- package/dist/config/schema.d.ts +103 -0
- package/dist/config/schema.js +49 -0
- package/dist/constants.d.ts +83 -0
- package/dist/constants.js +289 -0
- package/dist/cron/CronScheduler.d.ts +25 -0
- package/dist/cron/CronScheduler.js +149 -0
- package/dist/daemon/GracefulManager.d.ts +8 -0
- package/dist/daemon/GracefulManager.js +29 -0
- package/dist/daemon/ManagedProcess.d.ts +71 -0
- package/dist/daemon/ManagedProcess.js +1020 -0
- package/dist/daemon/Orchestrator.d.ts +51 -0
- package/dist/daemon/Orchestrator.js +416 -0
- package/dist/daemon/RotatingWriter.d.ts +27 -0
- package/dist/daemon/RotatingWriter.js +264 -0
- package/dist/daemon/index.d.ts +2 -0
- package/dist/daemon/index.js +106 -0
- package/dist/daemon/startDaemon.d.ts +30 -0
- package/dist/daemon/startDaemon.js +693 -0
- package/dist/deploy/CommandPoller.d.ts +13 -0
- package/dist/deploy/CommandPoller.js +53 -0
- package/dist/deploy/DeployExecutor.d.ts +33 -0
- package/dist/deploy/DeployExecutor.js +340 -0
- package/dist/deploy/config.d.ts +20 -0
- package/dist/deploy/config.js +161 -0
- package/dist/deploy/env.d.ts +2 -0
- package/dist/deploy/env.js +17 -0
- package/dist/deploy/tarball.d.ts +32 -0
- package/dist/deploy/tarball.js +243 -0
- package/dist/detect/framework.d.ts +2 -0
- package/dist/detect/framework.js +24 -0
- package/dist/ipc/DaemonClient.d.ts +31 -0
- package/dist/ipc/DaemonClient.js +248 -0
- package/dist/ipc/DaemonServer.d.ts +28 -0
- package/dist/ipc/DaemonServer.js +166 -0
- package/dist/ipc/MultiUserClient.d.ts +27 -0
- package/dist/ipc/MultiUserClient.js +203 -0
- package/dist/ipc/protocol.d.ts +7 -0
- package/dist/ipc/protocol.js +53 -0
- package/dist/ipc/restoreDaemon.d.ts +8 -0
- package/dist/ipc/restoreDaemon.js +19 -0
- package/dist/machine-id.d.ts +11 -0
- package/dist/machine-id.js +51 -0
- package/dist/mcp/auth.d.ts +118 -0
- package/dist/mcp/auth.js +245 -0
- package/dist/mcp/http.d.ts +20 -0
- package/dist/mcp/http.js +229 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/server.d.ts +37 -0
- package/dist/mcp/server.js +413 -0
- package/dist/probe/compute-fingerprint.d.ts +27 -0
- package/dist/probe/compute-fingerprint.js +65 -0
- package/dist/probe/parse-frames.d.ts +21 -0
- package/dist/probe/parse-frames.js +57 -0
- package/dist/probe/resolve-sourcemaps.d.ts +25 -0
- package/dist/probe/resolve-sourcemaps.js +281 -0
- package/dist/state/StateStore.d.ts +11 -0
- package/dist/state/StateStore.js +78 -0
- package/dist/telemetry/TelemetryReporter.d.ts +49 -0
- package/dist/telemetry/TelemetryReporter.js +451 -0
- package/dist/types/index.d.ts +373 -0
- package/dist/types/index.js +2 -0
- package/package.json +148 -0
- package/packages/cache/README.md +114 -0
- package/packages/cache/dist/CacheClient.d.ts +26 -0
- package/packages/cache/dist/CacheClient.d.ts.map +1 -0
- package/packages/cache/dist/CacheClient.js +174 -0
- package/packages/cache/dist/CacheClient.js.map +1 -0
- package/packages/cache/dist/CacheFileStore.d.ts +45 -0
- package/packages/cache/dist/CacheFileStore.d.ts.map +1 -0
- package/packages/cache/dist/CacheFileStore.js +446 -0
- package/packages/cache/dist/CacheFileStore.js.map +1 -0
- package/packages/cache/dist/CachePersistence.d.ts +9 -0
- package/packages/cache/dist/CachePersistence.d.ts.map +1 -0
- package/packages/cache/dist/CachePersistence.js +67 -0
- package/packages/cache/dist/CachePersistence.js.map +1 -0
- package/packages/cache/dist/CachePrimary.d.ts +25 -0
- package/packages/cache/dist/CachePrimary.d.ts.map +1 -0
- package/packages/cache/dist/CachePrimary.js +155 -0
- package/packages/cache/dist/CachePrimary.js.map +1 -0
- package/packages/cache/dist/CacheStore.d.ts +50 -0
- package/packages/cache/dist/CacheStore.d.ts.map +1 -0
- package/packages/cache/dist/CacheStore.js +271 -0
- package/packages/cache/dist/CacheStore.js.map +1 -0
- package/packages/cache/dist/constants.d.ts +6 -0
- package/packages/cache/dist/constants.d.ts.map +1 -0
- package/packages/cache/dist/constants.js +9 -0
- package/packages/cache/dist/constants.js.map +1 -0
- package/packages/cache/dist/index.d.ts +16 -0
- package/packages/cache/dist/index.d.ts.map +1 -0
- package/packages/cache/dist/index.js +86 -0
- package/packages/cache/dist/index.js.map +1 -0
- package/packages/cache/dist/serialize.d.ts +9 -0
- package/packages/cache/dist/serialize.d.ts.map +1 -0
- package/packages/cache/dist/serialize.js +40 -0
- package/packages/cache/dist/serialize.js.map +1 -0
- package/packages/cache/dist/types.d.ts +123 -0
- package/packages/cache/dist/types.d.ts.map +1 -0
- package/packages/cache/dist/types.js +2 -0
- package/packages/cache/dist/types.js.map +1 -0
- package/packages/cache/package.json +27 -0
- package/packages/cache/src/CacheClient.ts +227 -0
- package/packages/cache/src/CacheFileStore.ts +528 -0
- package/packages/cache/src/CachePersistence.ts +89 -0
- package/packages/cache/src/CachePrimary.ts +172 -0
- package/packages/cache/src/CacheStore.ts +308 -0
- package/packages/cache/src/constants.ts +10 -0
- package/packages/cache/src/index.ts +100 -0
- package/packages/cache/src/serialize.ts +49 -0
- package/packages/cache/src/types.ts +156 -0
- package/packages/cache/tsconfig.json +18 -0
- package/packages/cache/tsconfig.tsbuildinfo +1 -0
- package/packages/next/README.md +166 -0
- package/packages/next/dist/error-capture.d.ts +34 -0
- package/packages/next/dist/error-capture.d.ts.map +1 -0
- package/packages/next/dist/error-capture.js +130 -0
- package/packages/next/dist/error-capture.js.map +1 -0
- package/packages/next/dist/error-handler.d.ts +10 -0
- package/packages/next/dist/error-handler.d.ts.map +1 -0
- package/packages/next/dist/error-handler.js +186 -0
- package/packages/next/dist/error-handler.js.map +1 -0
- package/packages/next/dist/isr-cache.d.ts +9 -0
- package/packages/next/dist/isr-cache.d.ts.map +1 -0
- package/packages/next/dist/isr-cache.js +86 -0
- package/packages/next/dist/isr-cache.js.map +1 -0
- package/packages/next/dist/stream.d.ts +5 -0
- package/packages/next/dist/stream.d.ts.map +1 -0
- package/packages/next/dist/stream.js +22 -0
- package/packages/next/dist/stream.js.map +1 -0
- package/packages/next/dist/types.d.ts +33 -0
- package/packages/next/dist/types.d.ts.map +1 -0
- package/packages/next/dist/types.js +6 -0
- package/packages/next/dist/types.js.map +1 -0
- package/packages/next/dist/use-cache.d.ts +4 -0
- package/packages/next/dist/use-cache.d.ts.map +1 -0
- package/packages/next/dist/use-cache.js +86 -0
- package/packages/next/dist/use-cache.js.map +1 -0
- package/packages/next/dist/utils.d.ts +32 -0
- package/packages/next/dist/utils.d.ts.map +1 -0
- package/packages/next/dist/utils.js +88 -0
- package/packages/next/dist/utils.js.map +1 -0
- package/packages/next/package.json +52 -0
- package/packages/next/src/error-capture.ts +177 -0
- package/packages/next/src/error-handler.ts +221 -0
- package/packages/next/src/isr-cache.ts +100 -0
- package/packages/next/src/stream.ts +23 -0
- package/packages/next/src/types.ts +33 -0
- package/packages/next/src/use-cache.ts +99 -0
- package/packages/next/src/utils.ts +102 -0
- package/packages/next/tsconfig.json +19 -0
- package/packages/next/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { extractContext } from '@orkify/next/utils';
|
|
2
|
+
import { closeSync, existsSync, openSync, readFileSync, readSync, statSync } from 'node:fs';
|
|
3
|
+
import { dirname, isAbsolute, join } from 'node:path';
|
|
4
|
+
import { SourceMapConsumer } from 'source-map-js';
|
|
5
|
+
const SOURCEMAP_URL_RE = /\/[/*]#\s*sourceMappingURL=(\S+)\s*(?:\*\/)?$/;
|
|
6
|
+
/** Protocol prefixes used by bundlers in source map `sources` entries. */
|
|
7
|
+
const SOURCE_PROTOCOL_RE = /^(?:webpack:\/\/\/|webpack-internal:\/\/\/|webpack:\/\/[^/]*\/|vite-[\w-]+:\/\/)/;
|
|
8
|
+
/** Max bytes to read from the tail of a file to find sourceMappingURL. */
|
|
9
|
+
const TAIL_BYTES = 512;
|
|
10
|
+
/**
|
|
11
|
+
* Parse a base64-encoded inline source map from a data: URL.
|
|
12
|
+
* Returns the parsed JSON object, or null if parsing fails.
|
|
13
|
+
*/
|
|
14
|
+
function parseInlineSourceMap(dataUrl) {
|
|
15
|
+
try {
|
|
16
|
+
const base64Idx = dataUrl.indexOf('base64,');
|
|
17
|
+
if (base64Idx === -1)
|
|
18
|
+
return null;
|
|
19
|
+
const raw = Buffer.from(dataUrl.slice(base64Idx + 7), 'base64').toString('utf8');
|
|
20
|
+
return JSON.parse(raw);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Scan lines (newest-first) for a sourceMappingURL comment.
|
|
28
|
+
* Returns the URL string or null.
|
|
29
|
+
*/
|
|
30
|
+
function scanForSourceMapUrl(content) {
|
|
31
|
+
const lines = content.split('\n');
|
|
32
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
33
|
+
const match = lines[i].match(SOURCEMAP_URL_RE);
|
|
34
|
+
if (match)
|
|
35
|
+
return match[1];
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
function findSourceMap(filePath) {
|
|
40
|
+
try {
|
|
41
|
+
const stat = statSync(filePath);
|
|
42
|
+
const size = stat.size;
|
|
43
|
+
if (size === 0)
|
|
44
|
+
return null;
|
|
45
|
+
// Read only the tail of the file first (sourceMappingURL is always at the end).
|
|
46
|
+
// This is enough for external .map references (~40 chars).
|
|
47
|
+
const readSize = Math.min(size, TAIL_BYTES);
|
|
48
|
+
const buf = Buffer.alloc(readSize);
|
|
49
|
+
const fd = openSync(filePath, 'r');
|
|
50
|
+
try {
|
|
51
|
+
readSync(fd, buf, 0, readSize, size - readSize);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
closeSync(fd);
|
|
55
|
+
}
|
|
56
|
+
const tail = buf.toString('utf8');
|
|
57
|
+
let url = scanForSourceMapUrl(tail);
|
|
58
|
+
// If no match in the tail but we didn't read the whole file, the comment
|
|
59
|
+
// might be a long inline data: URL whose "//# sourceMappingURL=" prefix
|
|
60
|
+
// falls outside our 512-byte window. Fall back to full read.
|
|
61
|
+
if (!url && readSize < size) {
|
|
62
|
+
const full = readFileSync(filePath, 'utf8');
|
|
63
|
+
url = scanForSourceMapUrl(full);
|
|
64
|
+
}
|
|
65
|
+
if (!url)
|
|
66
|
+
return null;
|
|
67
|
+
if (url.startsWith('data:')) {
|
|
68
|
+
const data = parseInlineSourceMap(url);
|
|
69
|
+
return data ? { type: 'inline', data } : null;
|
|
70
|
+
}
|
|
71
|
+
// External .map file
|
|
72
|
+
const resolvedPath = isAbsolute(url) ? url : join(dirname(filePath), url);
|
|
73
|
+
return { type: 'file', path: resolvedPath };
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Strip bundler protocol prefixes from source paths.
|
|
81
|
+
* e.g. "webpack:///src/app.ts" → "src/app.ts"
|
|
82
|
+
* "webpack-internal:///./src/app.ts" → "./src/app.ts"
|
|
83
|
+
* "vite-node:///src/app.ts" → "src/app.ts"
|
|
84
|
+
*/
|
|
85
|
+
function stripSourceProtocol(source) {
|
|
86
|
+
return source.replace(SOURCE_PROTOCOL_RE, '');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve a source file path for display.
|
|
90
|
+
*
|
|
91
|
+
* For standalone bundler output (webpack/vite), `join(mapDir, source)` typically
|
|
92
|
+
* points to the real file. For Next.js, the source is relative to the project
|
|
93
|
+
* root (e.g. "src/app/page.tsx") but the .map lives deep inside .next/, so the
|
|
94
|
+
* naive join produces a wrong path. We walk up from the map directory looking
|
|
95
|
+
* for a package.json (project root marker) and resolve relative to that.
|
|
96
|
+
*/
|
|
97
|
+
function resolveDisplayPath(cleanSource, mapDir) {
|
|
98
|
+
if (isAbsolute(cleanSource))
|
|
99
|
+
return cleanSource;
|
|
100
|
+
// Fast path: source exists relative to the map directory (standalone bundles)
|
|
101
|
+
const naiveJoin = join(mapDir, cleanSource);
|
|
102
|
+
if (existsSync(naiveJoin))
|
|
103
|
+
return naiveJoin;
|
|
104
|
+
// Walk up to find the project root (package.json), then resolve relative to it
|
|
105
|
+
let dir = mapDir;
|
|
106
|
+
const root = dirname(dir) === dir ? dir : '/'; // filesystem root
|
|
107
|
+
while (dir !== root) {
|
|
108
|
+
if (existsSync(join(dir, 'package.json'))) {
|
|
109
|
+
const candidate = join(dir, cleanSource);
|
|
110
|
+
if (existsSync(candidate))
|
|
111
|
+
return candidate;
|
|
112
|
+
}
|
|
113
|
+
dir = dirname(dir);
|
|
114
|
+
}
|
|
115
|
+
// Fallback: return the clean relative source as-is (still readable)
|
|
116
|
+
return cleanSource;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Try to resolve a single frame using its source map.
|
|
120
|
+
* Returns the resolved frame or null if resolution fails.
|
|
121
|
+
*/
|
|
122
|
+
function resolveFrame(frame, consumerCache) {
|
|
123
|
+
// Find the source map (external file or inline data: URL)
|
|
124
|
+
const sourceMap = findSourceMap(frame.file);
|
|
125
|
+
let consumer;
|
|
126
|
+
let mapDir = dirname(frame.file);
|
|
127
|
+
if (sourceMap) {
|
|
128
|
+
if (sourceMap.type === 'inline') {
|
|
129
|
+
// Inline source map — create consumer directly from parsed data
|
|
130
|
+
try {
|
|
131
|
+
consumer = new SourceMapConsumer(sourceMap.data);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
consumer = null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// External .map file — use cache
|
|
139
|
+
mapDir = dirname(sourceMap.path);
|
|
140
|
+
consumer = consumerCache.get(sourceMap.path);
|
|
141
|
+
if (consumer === undefined) {
|
|
142
|
+
try {
|
|
143
|
+
const raw = readFileSync(sourceMap.path, 'utf8');
|
|
144
|
+
consumer = new SourceMapConsumer(JSON.parse(raw));
|
|
145
|
+
consumerCache.set(sourceMap.path, consumer);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
consumerCache.set(sourceMap.path, null);
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// Fallback: try <file>.map
|
|
156
|
+
const fallback = frame.file + '.map';
|
|
157
|
+
if (existsSync(fallback)) {
|
|
158
|
+
mapDir = dirname(fallback);
|
|
159
|
+
consumer = consumerCache.get(fallback);
|
|
160
|
+
if (consumer === undefined) {
|
|
161
|
+
try {
|
|
162
|
+
const raw = readFileSync(fallback, 'utf8');
|
|
163
|
+
consumer = new SourceMapConsumer(JSON.parse(raw));
|
|
164
|
+
consumerCache.set(fallback, consumer);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
consumerCache.set(fallback, null);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!consumer)
|
|
177
|
+
return null;
|
|
178
|
+
// Resolve the original position
|
|
179
|
+
const pos = consumer.originalPositionFor({
|
|
180
|
+
line: frame.line,
|
|
181
|
+
column: Math.max(0, (frame.column || 1) - 1),
|
|
182
|
+
});
|
|
183
|
+
if (!pos.source || !pos.line)
|
|
184
|
+
return null;
|
|
185
|
+
// Strip bundler protocol prefixes (webpack:///, vite-node://, etc.)
|
|
186
|
+
const cleanSource = stripSourceProtocol(pos.source);
|
|
187
|
+
// Get source content — prefer sourcesContent from the map, fall back to disk
|
|
188
|
+
let sourceContent = null;
|
|
189
|
+
try {
|
|
190
|
+
sourceContent = consumer.sourceContentFor(pos.source);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// Not available in sourcesContent
|
|
194
|
+
}
|
|
195
|
+
if (!sourceContent) {
|
|
196
|
+
// Try reading from disk using the cleaned source path
|
|
197
|
+
const displayPath = resolveDisplayPath(cleanSource, mapDir);
|
|
198
|
+
try {
|
|
199
|
+
sourceContent = readFileSync(displayPath, 'utf8');
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const context = extractContext(sourceContent, pos.line);
|
|
206
|
+
if (!context)
|
|
207
|
+
return null;
|
|
208
|
+
// Resolve the display file path from the cleaned source
|
|
209
|
+
const file = resolveDisplayPath(cleanSource, mapDir);
|
|
210
|
+
return {
|
|
211
|
+
frame: {
|
|
212
|
+
file,
|
|
213
|
+
line: pos.line,
|
|
214
|
+
column: (pos.column ?? 0) + 1,
|
|
215
|
+
pre: context.pre,
|
|
216
|
+
target: context.target,
|
|
217
|
+
post: context.post,
|
|
218
|
+
},
|
|
219
|
+
functionName: pos.name || null,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Resolve source maps for all frames in an error's source context.
|
|
224
|
+
*
|
|
225
|
+
* For each frame, attempts to find and parse the corresponding .map file,
|
|
226
|
+
* then replaces the minified location with the original source location.
|
|
227
|
+
* Frames that can't be resolved are kept as-is.
|
|
228
|
+
*
|
|
229
|
+
* Returns the resolved function name from the source map (if available)
|
|
230
|
+
* so the caller can use it for fingerprinting.
|
|
231
|
+
*/
|
|
232
|
+
export function resolveSourceMaps(sourceContext, topFrame) {
|
|
233
|
+
if (!sourceContext || sourceContext.length === 0) {
|
|
234
|
+
return { sourceContext, topFrame, resolvedFunctionName: null, resolved: false };
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
const consumerCache = new Map();
|
|
238
|
+
const resolvedFrames = [];
|
|
239
|
+
let anyResolved = false;
|
|
240
|
+
let resolvedTopFrame = null;
|
|
241
|
+
let resolvedFunctionName = null;
|
|
242
|
+
for (const frame of sourceContext) {
|
|
243
|
+
try {
|
|
244
|
+
const result = resolveFrame(frame, consumerCache);
|
|
245
|
+
if (result) {
|
|
246
|
+
resolvedFrames.push(result.frame);
|
|
247
|
+
anyResolved = true;
|
|
248
|
+
if (!resolvedTopFrame) {
|
|
249
|
+
resolvedTopFrame = {
|
|
250
|
+
file: result.frame.file,
|
|
251
|
+
line: result.frame.line,
|
|
252
|
+
column: result.frame.column,
|
|
253
|
+
};
|
|
254
|
+
resolvedFunctionName = result.functionName;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
resolvedFrames.push(frame);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Per-frame try/catch: one bad frame doesn't block others
|
|
263
|
+
resolvedFrames.push(frame);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (!anyResolved) {
|
|
267
|
+
return { sourceContext, topFrame, resolvedFunctionName: null, resolved: false };
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
sourceContext: resolvedFrames,
|
|
271
|
+
topFrame: resolvedTopFrame ?? topFrame,
|
|
272
|
+
resolvedFunctionName,
|
|
273
|
+
resolved: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Never crash the daemon — return original data
|
|
278
|
+
return { sourceContext, topFrame, resolvedFunctionName: null, resolved: false };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=resolve-sourcemaps.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { McpStartPayload, ProcessConfig, SavedState } from '../types/index.js';
|
|
2
|
+
export declare class StateStore {
|
|
3
|
+
private filePath;
|
|
4
|
+
constructor(filePath?: string);
|
|
5
|
+
save(processes: ProcessConfig[], mcp?: McpStartPayload): Promise<void>;
|
|
6
|
+
load(): Promise<ProcessConfig[]>;
|
|
7
|
+
loadFull(): Promise<SavedState>;
|
|
8
|
+
clear(): Promise<void>;
|
|
9
|
+
exists(): Promise<boolean>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=StateStore.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { parse, stringify } from 'yaml';
|
|
5
|
+
import { validateMcpState } from '../config/schema.js';
|
|
6
|
+
import { SNAPSHOT_FILE } from '../constants.js';
|
|
7
|
+
const STATE_VERSION = 1;
|
|
8
|
+
export class StateStore {
|
|
9
|
+
filePath;
|
|
10
|
+
constructor(filePath = SNAPSHOT_FILE) {
|
|
11
|
+
this.filePath = filePath;
|
|
12
|
+
}
|
|
13
|
+
async save(processes, mcp) {
|
|
14
|
+
const state = {
|
|
15
|
+
version: STATE_VERSION,
|
|
16
|
+
processes,
|
|
17
|
+
...(mcp ? { mcp } : {}),
|
|
18
|
+
};
|
|
19
|
+
// Ensure directory exists
|
|
20
|
+
const dir = dirname(this.filePath);
|
|
21
|
+
if (!existsSync(dir)) {
|
|
22
|
+
await mkdir(dir, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
// Atomic write: write to temp file then rename to prevent corruption
|
|
25
|
+
// if the process crashes mid-write
|
|
26
|
+
const tmpPath = this.filePath + '.tmp';
|
|
27
|
+
await writeFile(tmpPath, stringify(state, { defaultStringType: 'QUOTE_DOUBLE' }), 'utf-8');
|
|
28
|
+
await rename(tmpPath, this.filePath);
|
|
29
|
+
}
|
|
30
|
+
async load() {
|
|
31
|
+
const state = await this.loadFull();
|
|
32
|
+
return state.processes;
|
|
33
|
+
}
|
|
34
|
+
async loadFull() {
|
|
35
|
+
if (!existsSync(this.filePath)) {
|
|
36
|
+
return { processes: [] };
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const content = await readFile(this.filePath, 'utf-8');
|
|
40
|
+
const state = parse(content);
|
|
41
|
+
const version = state?.version ?? 1;
|
|
42
|
+
if (version !== STATE_VERSION) {
|
|
43
|
+
console.warn(`Snapshot file version mismatch: expected ${STATE_VERSION}, got ${version}`);
|
|
44
|
+
}
|
|
45
|
+
const processes = state?.processes || [];
|
|
46
|
+
// Coerce env values to strings — YAML parses unquoted values like
|
|
47
|
+
// `PORT: 3000` as numbers and `VERBOSE: yes` as booleans. Environment
|
|
48
|
+
// variables must always be strings.
|
|
49
|
+
for (const proc of processes) {
|
|
50
|
+
if (proc.env && typeof proc.env === 'object') {
|
|
51
|
+
for (const [key, value] of Object.entries(proc.env)) {
|
|
52
|
+
if (typeof value !== 'string') {
|
|
53
|
+
proc.env[key] = value === null || value === undefined ? '' : String(value);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const mcp = validateMcpState(state?.mcp) ? state.mcp : undefined;
|
|
59
|
+
if (state?.mcp && !mcp) {
|
|
60
|
+
console.warn('Snapshot contains invalid mcp section — ignoring');
|
|
61
|
+
}
|
|
62
|
+
return { ...state, processes, mcp };
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.error('Failed to load snapshot:', err);
|
|
66
|
+
return { processes: [] };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async clear() {
|
|
70
|
+
if (existsSync(this.filePath)) {
|
|
71
|
+
await writeFile(this.filePath, stringify({ version: STATE_VERSION, processes: [] }, { defaultStringType: 'QUOTE_DOUBLE' }), 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async exists() {
|
|
75
|
+
return existsSync(this.filePath);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=StateStore.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { AlertEvaluator } from '../alerts/AlertEvaluator.js';
|
|
3
|
+
import type { ConfigStore } from '../config/ConfigStore.js';
|
|
4
|
+
import type { Orchestrator } from '../daemon/Orchestrator.js';
|
|
5
|
+
import type { DeployStatus, TelemetryConfig, TelemetryEventType } from '../types/index.js';
|
|
6
|
+
export declare class TelemetryReporter extends EventEmitter {
|
|
7
|
+
private config;
|
|
8
|
+
private orchestrator;
|
|
9
|
+
private events;
|
|
10
|
+
private metrics;
|
|
11
|
+
private errors;
|
|
12
|
+
private logRings;
|
|
13
|
+
private logFlushBuffer;
|
|
14
|
+
private logFlushDropped;
|
|
15
|
+
private timer;
|
|
16
|
+
private hostName;
|
|
17
|
+
private agentName;
|
|
18
|
+
private machineId;
|
|
19
|
+
private hostInfo;
|
|
20
|
+
private _deployStatus;
|
|
21
|
+
private configStore;
|
|
22
|
+
private alertEvaluator;
|
|
23
|
+
private mcpCapable;
|
|
24
|
+
/** Previous cumulative cache counters per worker — keyed by "processName:workerId" */
|
|
25
|
+
private prevCacheCounters;
|
|
26
|
+
constructor(config: TelemetryConfig, orchestrator: Orchestrator, configStore?: ConfigStore | null, alertEvaluator?: AlertEvaluator | null);
|
|
27
|
+
start(): void;
|
|
28
|
+
shutdown(): Promise<void>;
|
|
29
|
+
private bindEvents;
|
|
30
|
+
/**
|
|
31
|
+
* Get logs for a specific worker. In cluster mode, worker stdout/stderr flows
|
|
32
|
+
* through the primary process (workerId -1), so if the worker-specific ring
|
|
33
|
+
* is empty we fall back to the primary's ring.
|
|
34
|
+
*/
|
|
35
|
+
private getWorkerLogs;
|
|
36
|
+
private clearWorkerLogs;
|
|
37
|
+
private pushEvent;
|
|
38
|
+
emitEvent(type: TelemetryEventType, processName: string, fields?: Record<string, unknown>): void;
|
|
39
|
+
setDeployStatus(status: DeployStatus | null): void;
|
|
40
|
+
setMcpCapable(v: boolean): void;
|
|
41
|
+
private collectAndFlush;
|
|
42
|
+
/**
|
|
43
|
+
* Drain the log flush buffer, capping at TELEMETRY_LOG_FLUSH_MAX_LINES per
|
|
44
|
+
* worker. When lines are dropped, prepend a truncation marker.
|
|
45
|
+
*/
|
|
46
|
+
private drainLogFlushBuffer;
|
|
47
|
+
private restoreBuffers;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=TelemetryReporter.d.ts.map
|