@surething/cockpit 1.0.216 → 1.0.218
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/.next-prod/BUILD_ID +1 -1
- package/.next-prod/app-path-routes-manifest.json +2 -2
- package/.next-prod/build-manifest.json +2 -2
- package/.next-prod/prerender-manifest.json +3 -3
- package/.next-prod/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/_global-error.html +1 -1
- package/.next-prod/server/app/_global-error.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next-prod/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/_not-found.html +1 -1
- package/.next-prod/server/app/_not-found.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/.next-prod/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next-prod/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next-prod/server/app/api/chat/deepseek/route.js +1 -1
- package/.next-prod/server/app/api/chat/route.js +1 -1
- package/.next-prod/server/app/api/extension/version/route.js.nft.json +1 -1
- package/.next-prod/server/app/api/projectGraph/file-functions/route.js +1 -1
- package/.next-prod/server/app/api/scheduled-tasks/route.js +1 -1
- package/.next-prod/server/app/api/terminal/bubble-order/route.js +1 -1
- package/.next-prod/server/app/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/project/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app/review/[id]/page_client-reference-manifest.js +1 -1
- package/.next-prod/server/app-paths-manifest.json +2 -2
- package/.next-prod/server/chunks/2939.js +1 -1
- package/.next-prod/server/chunks/8916.js +1 -1
- package/.next-prod/server/chunks/9658.js +7 -7
- package/.next-prod/server/chunks/9877.js +1 -1
- package/.next-prod/server/functions-config-manifest.json +1 -0
- package/.next-prod/server/middleware-build-manifest.js +1 -1
- package/.next-prod/server/pages/404.html +1 -1
- package/.next-prod/server/pages/500.html +1 -1
- package/.next-prod/server/server-reference-manifest.json +1 -1
- package/.next-prod/static/chunks/6345-2637497e8b101740.js +14 -0
- package/.next-prod/static/chunks/6917-ed0e9c62a123d529.js +29 -0
- package/.next-prod/static/chunks/app/{layout-a0362651ba6e6e6f.js → layout-1659a95e6c4a6bb5.js} +1 -1
- package/.next-prod/static/chunks/app/{page-1b14cabf47df9ff7.js → page-afcbd897b4c3600f.js} +1 -1
- package/.next-prod/static/chunks/app/project/{page-1b14cabf47df9ff7.js → page-afcbd897b4c3600f.js} +1 -1
- package/.next-prod/static/css/f4a773117ca8af75.css +1 -0
- package/.next-prod/trace +13 -13
- package/.next-prod/trace-build +1 -1
- package/README.md +8 -7
- package/README.zh.md +8 -7
- package/bin/cock-browser.messages.mjs +176 -0
- package/bin/cock-browser.mjs +290 -18
- package/bin/cock-codegraph.mjs +21 -6
- package/bin/cock-connection.mjs +151 -0
- package/bin/cock.mjs +12 -1
- package/bin/setup-dev.mjs +15 -13
- package/chrome-extension/automation.js +684 -32
- package/chrome-extension/manifest.json +1 -1
- package/chrome-extension/messages.js +45 -0
- package/dist/{chunk-CZWJPTRO.mjs → chunk-GCYLMG43.mjs} +2486 -1047
- package/dist/chunk-O4P2J44N.mjs +314 -0
- package/dist/{chunk-KRTISG5I.mjs → chunk-WOM47O75.mjs} +245 -10
- package/dist/httpApi.mjs +140 -7
- package/dist/scheduledTasks.mjs +15 -1159
- package/dist/{server-OSOMFNXR.mjs → server-SNB4H35J.mjs} +8 -2
- package/dist/wsServer.mjs +27 -19
- package/package.json +3 -5
- package/server.mjs +5 -1
- package/.next-prod/static/chunks/5188-415582403ef0e29c.js +0 -29
- package/.next-prod/static/chunks/6345-e5ceeb2aeb698eb6.js +0 -14
- package/.next-prod/static/css/cc6d733cdf607b30.css +0 -1
- package/dist/chunk-ZJ6CC3MH.mjs +0 -223
- /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → bOkuiIr_nWzG5GjPLNqdN}/_buildManifest.js +0 -0
- /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → bOkuiIr_nWzG5GjPLNqdN}/_ssgManifest.js +0 -0
package/dist/scheduledTasks.mjs
CHANGED
|
@@ -1,1170 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
AgentError,
|
|
3
|
-
Config_exports,
|
|
4
|
-
Context_exports,
|
|
5
|
-
DBError,
|
|
6
|
-
Duration_exports,
|
|
7
|
-
Effect_exports,
|
|
8
|
-
Fiber_exports,
|
|
9
|
-
Layer_exports,
|
|
10
|
-
LogLevel_exports,
|
|
11
|
-
Logger_exports,
|
|
12
|
-
ManagedRuntime_exports,
|
|
13
|
-
Option_exports,
|
|
14
|
-
Queue_exports,
|
|
15
|
-
Ref_exports,
|
|
16
|
-
Schedule_exports,
|
|
17
|
-
Stream_exports,
|
|
18
|
-
Tracer_exports,
|
|
19
2
|
getSessionTitle,
|
|
20
3
|
updateGlobalState
|
|
21
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-O4P2J44N.mjs";
|
|
22
5
|
import {
|
|
6
|
+
AgentError,
|
|
7
|
+
AppRuntime,
|
|
23
8
|
CLAUDE2_DIR,
|
|
9
|
+
CockpitConfig,
|
|
10
|
+
Effect_exports,
|
|
24
11
|
SCHEDULED_TASKS_FILE,
|
|
25
|
-
createNeo4jDriver,
|
|
26
12
|
readJsonFile,
|
|
27
|
-
runCypherWithDriver,
|
|
28
13
|
writeJsonFile
|
|
29
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GCYLMG43.mjs";
|
|
30
15
|
import "./chunk-7P6ASYW6.mjs";
|
|
31
16
|
|
|
32
17
|
// packages/feature/agent/src/server/scheduledTasks.ts
|
|
33
|
-
import { query as query2 } from "@anthropic-ai/claude-agent-sdk";
|
|
34
|
-
|
|
35
|
-
// packages/shared/utils/src/ollamaEnv.ts
|
|
36
|
-
var DEFAULT_BASE = "http://127.0.0.1:11434";
|
|
37
|
-
function getOllamaBaseURL() {
|
|
38
|
-
const raw = process.env.OLLAMA_BASE_URL || DEFAULT_BASE;
|
|
39
|
-
return raw.replace(/\/v1\/?$/, "").replace(/\/+$/, "");
|
|
40
|
-
}
|
|
41
|
-
function getOllamaOpenAIBaseURL() {
|
|
42
|
-
return `${getOllamaBaseURL()}/v1/`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// packages/shared/effect-core/src/logger.ts
|
|
46
|
-
var parseLevel = (raw) => {
|
|
47
|
-
switch ((raw ?? "").toLowerCase()) {
|
|
48
|
-
case "all":
|
|
49
|
-
return LogLevel_exports.All;
|
|
50
|
-
case "trace":
|
|
51
|
-
return LogLevel_exports.Trace;
|
|
52
|
-
case "debug":
|
|
53
|
-
return LogLevel_exports.Debug;
|
|
54
|
-
case "info":
|
|
55
|
-
return LogLevel_exports.Info;
|
|
56
|
-
case "warning":
|
|
57
|
-
case "warn":
|
|
58
|
-
return LogLevel_exports.Warning;
|
|
59
|
-
case "error":
|
|
60
|
-
return LogLevel_exports.Error;
|
|
61
|
-
case "fatal":
|
|
62
|
-
return LogLevel_exports.Fatal;
|
|
63
|
-
case "none":
|
|
64
|
-
return LogLevel_exports.None;
|
|
65
|
-
default:
|
|
66
|
-
return LogLevel_exports.Info;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
var LoggerLivePretty = Layer_exports.mergeAll(
|
|
70
|
-
Logger_exports.pretty,
|
|
71
|
-
Logger_exports.minimumLogLevel(parseLevel(process.env.COCKPIT_LOG_LEVEL))
|
|
72
|
-
);
|
|
73
|
-
var appendLogFile = async (line, filePath) => {
|
|
74
|
-
const { appendFile, mkdir } = await import("fs/promises");
|
|
75
|
-
const { dirname } = await import("path");
|
|
76
|
-
try {
|
|
77
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
78
|
-
await appendFile(filePath, line + "\n", "utf-8");
|
|
79
|
-
} catch {
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
var normalizeMessage = (m) => {
|
|
83
|
-
if (Array.isArray(m)) {
|
|
84
|
-
return m.length === 1 ? m[0] : m;
|
|
85
|
-
}
|
|
86
|
-
return m;
|
|
87
|
-
};
|
|
88
|
-
var fileLogger = (filePath) => Logger_exports.make(({ logLevel, message, date, fiberId, spans, annotations }) => {
|
|
89
|
-
const payload = {
|
|
90
|
-
time: date.toISOString(),
|
|
91
|
-
level: logLevel.label,
|
|
92
|
-
// fiberId is a FiberId object; extract its numeric id
|
|
93
|
-
fiber: typeof fiberId === "object" && fiberId !== null && "id" in fiberId ? fiberId.id : String(fiberId),
|
|
94
|
-
msg: normalizeMessage(message),
|
|
95
|
-
spans: Array.from(spans).map((s) => ({
|
|
96
|
-
label: s.label,
|
|
97
|
-
startTime: s.startTime
|
|
98
|
-
})),
|
|
99
|
-
annotations: Object.fromEntries(annotations)
|
|
100
|
-
};
|
|
101
|
-
void appendLogFile(JSON.stringify(payload), filePath);
|
|
102
|
-
});
|
|
103
|
-
var LoggerLiveProd = (logFile) => Layer_exports.mergeAll(
|
|
104
|
-
Logger_exports.pretty,
|
|
105
|
-
// still write to stdout for ops readability
|
|
106
|
-
Logger_exports.add(fileLogger(logFile)),
|
|
107
|
-
// also append to the file
|
|
108
|
-
Logger_exports.minimumLogLevel(parseLevel(process.env.COCKPIT_LOG_LEVEL))
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// packages/shared/effect-core/src/spanRecorder.ts
|
|
112
|
-
var MAX_SPANS = 500;
|
|
113
|
-
var g = globalThis;
|
|
114
|
-
var ring = g.__cockpitSpanRing ??= {
|
|
115
|
-
buffer: [],
|
|
116
|
-
index: /* @__PURE__ */ new Map()
|
|
117
|
-
};
|
|
118
|
-
function recordSpanStart(span) {
|
|
119
|
-
ring.buffer.push(span);
|
|
120
|
-
ring.index.set(span.spanId, ring.buffer.length - 1);
|
|
121
|
-
if (ring.buffer.length > MAX_SPANS) {
|
|
122
|
-
const removed = ring.buffer.shift();
|
|
123
|
-
ring.index.clear();
|
|
124
|
-
for (let i = 0; i < ring.buffer.length; i++) {
|
|
125
|
-
ring.index.set(ring.buffer[i].spanId, i);
|
|
126
|
-
}
|
|
127
|
-
void removed;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
function recordSpanEnd(spanId, endTimeNs, exit) {
|
|
131
|
-
const idx = ring.index.get(spanId);
|
|
132
|
-
if (idx === void 0) return;
|
|
133
|
-
const existing = ring.buffer[idx];
|
|
134
|
-
if (!existing) return;
|
|
135
|
-
const startNs = BigInt(existing.startTimeNs);
|
|
136
|
-
const durationMs = Number(endTimeNs - startNs) / 1e6;
|
|
137
|
-
ring.buffer[idx] = {
|
|
138
|
-
...existing,
|
|
139
|
-
endTimeNs: endTimeNs.toString(),
|
|
140
|
-
durationMs: Math.round(durationMs * 100) / 100,
|
|
141
|
-
status: exit._tag === "Success" ? "ok" : "error",
|
|
142
|
-
errorMessage: exit._tag === "Failure" ? prettyPrintCause(exit.cause) : void 0
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
function recordSpanAttribute(spanId, key, value) {
|
|
146
|
-
const idx = ring.index.get(spanId);
|
|
147
|
-
if (idx === void 0) return;
|
|
148
|
-
const existing = ring.buffer[idx];
|
|
149
|
-
if (!existing) return;
|
|
150
|
-
ring.buffer[idx] = {
|
|
151
|
-
...existing,
|
|
152
|
-
attributes: { ...existing.attributes, [key]: value }
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function recordSpanEvent(spanId, eventName, timeNs, attributes) {
|
|
156
|
-
const idx = ring.index.get(spanId);
|
|
157
|
-
if (idx === void 0) return;
|
|
158
|
-
const existing = ring.buffer[idx];
|
|
159
|
-
if (!existing) return;
|
|
160
|
-
ring.buffer[idx] = {
|
|
161
|
-
...existing,
|
|
162
|
-
events: [
|
|
163
|
-
...existing.events,
|
|
164
|
-
{ name: eventName, timeNs: timeNs.toString(), attributes }
|
|
165
|
-
]
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
function prettyPrintCause(cause) {
|
|
169
|
-
if (cause instanceof Error) return cause.message;
|
|
170
|
-
if (typeof cause === "string") return cause;
|
|
171
|
-
try {
|
|
172
|
-
return JSON.stringify(cause);
|
|
173
|
-
} catch {
|
|
174
|
-
return String(cause);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function makeStartedRecord(spanId, traceId, parentSpanId, name, kind, startTimeNs) {
|
|
178
|
-
return {
|
|
179
|
-
traceId,
|
|
180
|
-
spanId,
|
|
181
|
-
parentSpanId,
|
|
182
|
-
name,
|
|
183
|
-
kind,
|
|
184
|
-
startTimeNs: startTimeNs.toString(),
|
|
185
|
-
endTimeNs: null,
|
|
186
|
-
durationMs: null,
|
|
187
|
-
attributes: {},
|
|
188
|
-
events: [],
|
|
189
|
-
status: "started"
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
function getParentSpanId(parent) {
|
|
193
|
-
return Option_exports.isSome(parent) ? parent.value.spanId : null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// packages/shared/effect-core/src/tracer.ts
|
|
197
|
-
var randomHexString = (length) => {
|
|
198
|
-
const chars = "abcdef0123456789";
|
|
199
|
-
let s = "";
|
|
200
|
-
for (let i = 0; i < length; i++) {
|
|
201
|
-
s += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
202
|
-
}
|
|
203
|
-
return s;
|
|
204
|
-
};
|
|
205
|
-
var RecordingSpan = class {
|
|
206
|
-
constructor(name, parent, context, links, startTime, kind) {
|
|
207
|
-
this.name = name;
|
|
208
|
-
this.parent = parent;
|
|
209
|
-
this.context = context;
|
|
210
|
-
this.startTime = startTime;
|
|
211
|
-
this.kind = kind;
|
|
212
|
-
this._tag = "Span";
|
|
213
|
-
this.sampled = true;
|
|
214
|
-
this.attributes = /* @__PURE__ */ new Map();
|
|
215
|
-
this.events = [];
|
|
216
|
-
this.traceId = Option_exports.isSome(parent) ? parent.value.traceId : randomHexString(32);
|
|
217
|
-
this.spanId = randomHexString(16);
|
|
218
|
-
this.status = { _tag: "Started", startTime };
|
|
219
|
-
this.links = Array.from(links);
|
|
220
|
-
recordSpanStart(
|
|
221
|
-
makeStartedRecord(
|
|
222
|
-
this.spanId,
|
|
223
|
-
this.traceId,
|
|
224
|
-
getParentSpanId(parent),
|
|
225
|
-
name,
|
|
226
|
-
kind,
|
|
227
|
-
startTime
|
|
228
|
-
)
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
end(endTime, exit) {
|
|
232
|
-
this.status = {
|
|
233
|
-
_tag: "Ended",
|
|
234
|
-
endTime,
|
|
235
|
-
exit,
|
|
236
|
-
startTime: this.status.startTime
|
|
237
|
-
};
|
|
238
|
-
recordSpanEnd(
|
|
239
|
-
this.spanId,
|
|
240
|
-
endTime,
|
|
241
|
-
exit._tag === "Success" ? { _tag: "Success" } : { _tag: "Failure", cause: exit.cause }
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
attribute(key, value) {
|
|
245
|
-
this.attributes.set(key, value);
|
|
246
|
-
recordSpanAttribute(this.spanId, key, value);
|
|
247
|
-
}
|
|
248
|
-
event(name, startTime, attributes) {
|
|
249
|
-
this.events.push([name, startTime, attributes ?? {}]);
|
|
250
|
-
recordSpanEvent(this.spanId, name, startTime, attributes);
|
|
251
|
-
}
|
|
252
|
-
addLinks(links) {
|
|
253
|
-
this.links.push(...links);
|
|
254
|
-
}
|
|
255
|
-
};
|
|
256
|
-
var recordingTracer = Tracer_exports.make({
|
|
257
|
-
span: (name, parent, context, links, startTime, kind) => new RecordingSpan(name, parent, context, links, startTime, kind),
|
|
258
|
-
context: (f) => f()
|
|
259
|
-
});
|
|
260
|
-
var TracerLivePretty = Layer_exports.succeed(
|
|
261
|
-
Tracer_exports.Tracer,
|
|
262
|
-
recordingTracer
|
|
263
|
-
);
|
|
264
|
-
var TracerLiveNoop = Layer_exports.empty;
|
|
265
|
-
|
|
266
|
-
// packages/shared/effect-core/src/config.ts
|
|
267
|
-
var envConfig = Config_exports.literal("dev", "prod")("COCKPIT_ENV").pipe(
|
|
268
|
-
Config_exports.withDefault("prod")
|
|
269
|
-
);
|
|
270
|
-
var hostConfig = Config_exports.string("COCKPIT_HOST").pipe(
|
|
271
|
-
Config_exports.withDefault("127.0.0.1")
|
|
272
|
-
);
|
|
273
|
-
var portConfig = Config_exports.integer("COCKPIT_PORT").pipe(
|
|
274
|
-
Config_exports.orElse(() => Config_exports.integer("PORT")),
|
|
275
|
-
Config_exports.withDefault(3457)
|
|
276
|
-
);
|
|
277
|
-
var openProjectConfig = Config_exports.option(
|
|
278
|
-
Config_exports.string("COCKPIT_OPEN_PROJECT")
|
|
279
|
-
).pipe(
|
|
280
|
-
Config_exports.map((opt) => opt._tag === "Some" ? opt.value : void 0)
|
|
281
|
-
);
|
|
282
|
-
var noOpenConfig = Config_exports.boolean("COCKPIT_NO_OPEN").pipe(
|
|
283
|
-
Config_exports.withDefault(false)
|
|
284
|
-
);
|
|
285
|
-
var logLevelConfig = Config_exports.string("COCKPIT_LOG_LEVEL").pipe(
|
|
286
|
-
Config_exports.withDefault("info")
|
|
287
|
-
);
|
|
288
|
-
var cockpitDirConfigOpt = Config_exports.option(Config_exports.string("COCKPIT_DIR"));
|
|
289
|
-
var CockpitConfig = Effect_exports.gen(
|
|
290
|
-
function* () {
|
|
291
|
-
const env = yield* envConfig;
|
|
292
|
-
const host = yield* hostConfig;
|
|
293
|
-
const port = yield* portConfig;
|
|
294
|
-
const openProject = yield* openProjectConfig;
|
|
295
|
-
const noOpen = yield* noOpenConfig;
|
|
296
|
-
const logLevel = yield* logLevelConfig;
|
|
297
|
-
const cockpitDirOpt = yield* cockpitDirConfigOpt;
|
|
298
|
-
const cockpitDir = yield* Effect_exports.sync(() => {
|
|
299
|
-
if (cockpitDirOpt._tag === "Some") return cockpitDirOpt.value;
|
|
300
|
-
const env2 = typeof process !== "undefined" ? process.env : void 0;
|
|
301
|
-
const home = env2?.HOME || env2?.USERPROFILE || ".";
|
|
302
|
-
return home + "/.cockpit";
|
|
303
|
-
});
|
|
304
|
-
const logFile = cockpitDir + "/logs/cockpit.log";
|
|
305
|
-
return {
|
|
306
|
-
env,
|
|
307
|
-
host,
|
|
308
|
-
port: port === 3457 && env === "dev" ? 3456 : port,
|
|
309
|
-
// dev defaults to 3456
|
|
310
|
-
cockpitDir,
|
|
311
|
-
openProject,
|
|
312
|
-
openBrowser: !noOpen,
|
|
313
|
-
logLevel,
|
|
314
|
-
logFile
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
).pipe(Effect_exports.orDie);
|
|
318
|
-
var ConfigLive = Layer_exports.empty;
|
|
319
|
-
|
|
320
|
-
// packages/shared/effect-core/src/schedule.ts
|
|
321
|
-
var wsReconnect = Schedule_exports.exponential(
|
|
322
|
-
Duration_exports.seconds(1),
|
|
323
|
-
1.5
|
|
324
|
-
).pipe(
|
|
325
|
-
Schedule_exports.either(Schedule_exports.spaced(Duration_exports.seconds(10))),
|
|
326
|
-
// cap at 10s
|
|
327
|
-
Schedule_exports.intersect(Schedule_exports.recurs(10))
|
|
328
|
-
// up to 10 attempts
|
|
329
|
-
);
|
|
330
|
-
var dbRetry = Schedule_exports.exponential(
|
|
331
|
-
Duration_exports.millis(200),
|
|
332
|
-
2
|
|
333
|
-
).pipe(
|
|
334
|
-
Schedule_exports.either(Schedule_exports.spaced(Duration_exports.seconds(5))),
|
|
335
|
-
Schedule_exports.intersect(Schedule_exports.recurs(5))
|
|
336
|
-
);
|
|
337
|
-
var agentRetry = Schedule_exports.exponential(
|
|
338
|
-
Duration_exports.seconds(1),
|
|
339
|
-
2
|
|
340
|
-
).pipe(
|
|
341
|
-
Schedule_exports.jittered,
|
|
342
|
-
// jitter to avoid thundering herd
|
|
343
|
-
Schedule_exports.either(Schedule_exports.spaced(Duration_exports.seconds(30))),
|
|
344
|
-
Schedule_exports.intersect(Schedule_exports.recurs(8))
|
|
345
|
-
);
|
|
346
|
-
var wsHeartbeat = Schedule_exports.spaced(Duration_exports.seconds(30));
|
|
347
|
-
var shortPoll = Schedule_exports.spaced(Duration_exports.seconds(1));
|
|
348
|
-
var longPoll = Schedule_exports.spaced(Duration_exports.seconds(30));
|
|
349
|
-
var fileChangeDebounce = Duration_exports.millis(50);
|
|
350
|
-
var cron = Schedule_exports.cron;
|
|
351
|
-
|
|
352
|
-
// packages/feature/console/src/effect/pgLive.ts
|
|
353
|
-
import pg from "pg";
|
|
354
|
-
|
|
355
|
-
// packages/shared/effect-services/src/db.ts
|
|
356
|
-
var PgService = Context_exports.GenericTag("@cockpit/PgService");
|
|
357
|
-
var MySQLService = Context_exports.GenericTag("@cockpit/MySQLService");
|
|
358
|
-
var RedisService = Context_exports.GenericTag("@cockpit/RedisService");
|
|
359
|
-
var Neo4jService = Context_exports.GenericTag("@cockpit/Neo4jService");
|
|
360
|
-
var MongoService = Context_exports.GenericTag("@cockpit/MongoService");
|
|
361
|
-
|
|
362
|
-
// packages/shared/effect-services/src/agent.ts
|
|
363
|
-
var AgentService = Context_exports.GenericTag("@cockpit/AgentService");
|
|
364
|
-
|
|
365
|
-
// packages/shared/effect-services/src/scheduler.ts
|
|
366
|
-
var Scheduler = Context_exports.GenericTag("@cockpit/Scheduler");
|
|
367
|
-
|
|
368
|
-
// packages/feature/console/src/effect/pgLive.ts
|
|
369
|
-
var { Pool } = pg;
|
|
370
|
-
var handleAsync = (op, f) => Effect_exports.tryPromise({
|
|
371
|
-
try: f,
|
|
372
|
-
catch: (cause) => new DBError({ db: "pg", op, cause })
|
|
373
|
-
});
|
|
374
|
-
var acquirePool = (poolsRef, id, connectionString) => Effect_exports.gen(function* () {
|
|
375
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
376
|
-
const existing = pools.get(id);
|
|
377
|
-
if (existing && existing.connectionString === connectionString) {
|
|
378
|
-
return existing.pool;
|
|
379
|
-
}
|
|
380
|
-
if (existing) {
|
|
381
|
-
yield* handleAsync("end", () => existing.pool.end()).pipe(
|
|
382
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
const pool = new Pool({
|
|
386
|
-
connectionString,
|
|
387
|
-
max: 5,
|
|
388
|
-
idleTimeoutMillis: 6e4,
|
|
389
|
-
connectionTimeoutMillis: 1e4
|
|
390
|
-
});
|
|
391
|
-
yield* Ref_exports.update(poolsRef, (m) => {
|
|
392
|
-
const next = new Map(m);
|
|
393
|
-
next.set(id, { pool, connectionString, createdAt: Date.now() });
|
|
394
|
-
return next;
|
|
395
|
-
});
|
|
396
|
-
return pool;
|
|
397
|
-
});
|
|
398
|
-
var disconnectPool = (poolsRef, id) => Effect_exports.gen(function* () {
|
|
399
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
400
|
-
const managed = pools.get(id);
|
|
401
|
-
if (!managed) return;
|
|
402
|
-
yield* handleAsync("disconnect", () => managed.pool.end()).pipe(
|
|
403
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
404
|
-
);
|
|
405
|
-
yield* Ref_exports.update(poolsRef, (m) => {
|
|
406
|
-
const next = new Map(m);
|
|
407
|
-
next.delete(id);
|
|
408
|
-
return next;
|
|
409
|
-
});
|
|
410
|
-
});
|
|
411
|
-
var PgServiceLive = Layer_exports.scoped(
|
|
412
|
-
PgService,
|
|
413
|
-
Effect_exports.gen(function* () {
|
|
414
|
-
const poolsRef = yield* Ref_exports.make(/* @__PURE__ */ new Map());
|
|
415
|
-
yield* Effect_exports.addFinalizer(
|
|
416
|
-
() => Effect_exports.gen(function* () {
|
|
417
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
418
|
-
for (const { pool } of pools.values()) {
|
|
419
|
-
yield* Effect_exports.tryPromise({
|
|
420
|
-
try: () => pool.end(),
|
|
421
|
-
catch: (cause) => new DBError({ db: "pg", op: "shutdown end", cause })
|
|
422
|
-
}).pipe(Effect_exports.orElse(() => Effect_exports.void));
|
|
423
|
-
}
|
|
424
|
-
yield* Ref_exports.set(poolsRef, /* @__PURE__ */ new Map());
|
|
425
|
-
yield* Effect_exports.logInfo(
|
|
426
|
-
`[PgServiceLive] disposed ${pools.size} pool(s)`
|
|
427
|
-
);
|
|
428
|
-
})
|
|
429
|
-
);
|
|
430
|
-
return PgService.of({
|
|
431
|
-
query: (id, connStr, sql, params) => Effect_exports.gen(function* () {
|
|
432
|
-
const pool = yield* acquirePool(poolsRef, id, connStr);
|
|
433
|
-
const result = yield* handleAsync(
|
|
434
|
-
"query",
|
|
435
|
-
() => pool.query(sql, params)
|
|
436
|
-
);
|
|
437
|
-
return result.rows;
|
|
438
|
-
}).pipe(Effect_exports.withSpan("pg.query", { attributes: { id } })),
|
|
439
|
-
queryWithMeta: (id, connStr, sql, params) => Effect_exports.gen(function* () {
|
|
440
|
-
const pool = yield* acquirePool(poolsRef, id, connStr);
|
|
441
|
-
const start = performance.now();
|
|
442
|
-
const result = yield* handleAsync(
|
|
443
|
-
"queryWithMeta",
|
|
444
|
-
() => pool.query(sql, params)
|
|
445
|
-
);
|
|
446
|
-
const duration = Math.round((performance.now() - start) * 100) / 100;
|
|
447
|
-
const meta = {
|
|
448
|
-
rows: result.rows ?? [],
|
|
449
|
-
fields: result.fields ? result.fields.map(
|
|
450
|
-
(f) => ({
|
|
451
|
-
name: f.name,
|
|
452
|
-
dataTypeID: f.dataTypeID
|
|
453
|
-
})
|
|
454
|
-
) : null,
|
|
455
|
-
rowCount: result.rowCount ?? null,
|
|
456
|
-
command: result.command ?? null,
|
|
457
|
-
duration
|
|
458
|
-
};
|
|
459
|
-
return meta;
|
|
460
|
-
}).pipe(
|
|
461
|
-
Effect_exports.withSpan("pg.queryWithMeta", { attributes: { id } })
|
|
462
|
-
),
|
|
463
|
-
stream: (id, connStr, sql, params) => Stream_exports.unwrap(
|
|
464
|
-
Effect_exports.gen(function* () {
|
|
465
|
-
const pool = yield* acquirePool(poolsRef, id, connStr);
|
|
466
|
-
const result = yield* handleAsync(
|
|
467
|
-
"query",
|
|
468
|
-
() => pool.query(sql, params)
|
|
469
|
-
);
|
|
470
|
-
return Stream_exports.fromIterable(result.rows);
|
|
471
|
-
})
|
|
472
|
-
),
|
|
473
|
-
withTx: (id, connStr, f) => Effect_exports.gen(function* () {
|
|
474
|
-
const pool = yield* acquirePool(poolsRef, id, connStr);
|
|
475
|
-
const client = yield* handleAsync("connect", () => pool.connect());
|
|
476
|
-
yield* handleAsync("BEGIN", () => client.query("BEGIN"));
|
|
477
|
-
const tx = {
|
|
478
|
-
query: (sql, params) => handleAsync(
|
|
479
|
-
"tx.query",
|
|
480
|
-
() => client.query(sql, params).then((r) => r.rows)
|
|
481
|
-
)
|
|
482
|
-
};
|
|
483
|
-
const result = yield* f(tx).pipe(
|
|
484
|
-
Effect_exports.tapBoth({
|
|
485
|
-
onSuccess: () => handleAsync("COMMIT", () => client.query("COMMIT")),
|
|
486
|
-
onFailure: () => handleAsync(
|
|
487
|
-
"ROLLBACK",
|
|
488
|
-
() => client.query("ROLLBACK")
|
|
489
|
-
).pipe(Effect_exports.orElse(() => Effect_exports.void))
|
|
490
|
-
}),
|
|
491
|
-
Effect_exports.ensuring(Effect_exports.sync(() => client.release()))
|
|
492
|
-
);
|
|
493
|
-
return result;
|
|
494
|
-
}).pipe(Effect_exports.withSpan("pg.withTx", { attributes: { id } })),
|
|
495
|
-
disconnect: (id) => disconnectPool(poolsRef, id)
|
|
496
|
-
});
|
|
497
|
-
})
|
|
498
|
-
);
|
|
499
|
-
|
|
500
|
-
// packages/feature/console/src/effect/mysqlLive.ts
|
|
501
|
-
import mysql from "mysql2/promise";
|
|
502
|
-
var handleAsync2 = (op, f) => Effect_exports.tryPromise({
|
|
503
|
-
try: f,
|
|
504
|
-
catch: (cause) => new DBError({ db: "mysql", op, cause })
|
|
505
|
-
});
|
|
506
|
-
var acquirePool2 = (poolsRef, id, connectionString) => Effect_exports.gen(function* () {
|
|
507
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
508
|
-
const existing = pools.get(id);
|
|
509
|
-
if (existing && existing.connectionString === connectionString) {
|
|
510
|
-
return existing.pool;
|
|
511
|
-
}
|
|
512
|
-
if (existing) {
|
|
513
|
-
yield* handleAsync2("end", () => existing.pool.end()).pipe(
|
|
514
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
515
|
-
);
|
|
516
|
-
}
|
|
517
|
-
const pool = mysql.createPool({
|
|
518
|
-
uri: connectionString,
|
|
519
|
-
connectionLimit: 5,
|
|
520
|
-
idleTimeout: 6e4,
|
|
521
|
-
connectTimeout: 1e4
|
|
522
|
-
});
|
|
523
|
-
yield* Ref_exports.update(poolsRef, (m) => {
|
|
524
|
-
const next = new Map(m);
|
|
525
|
-
next.set(id, { pool, connectionString, createdAt: Date.now() });
|
|
526
|
-
return next;
|
|
527
|
-
});
|
|
528
|
-
return pool;
|
|
529
|
-
});
|
|
530
|
-
var disconnectPool2 = (poolsRef, id) => Effect_exports.gen(function* () {
|
|
531
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
532
|
-
const managed = pools.get(id);
|
|
533
|
-
if (!managed) return;
|
|
534
|
-
yield* handleAsync2("disconnect", () => managed.pool.end()).pipe(
|
|
535
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
536
|
-
);
|
|
537
|
-
yield* Ref_exports.update(poolsRef, (m) => {
|
|
538
|
-
const next = new Map(m);
|
|
539
|
-
next.delete(id);
|
|
540
|
-
return next;
|
|
541
|
-
});
|
|
542
|
-
});
|
|
543
|
-
var MySQLServiceLive = Layer_exports.scoped(
|
|
544
|
-
MySQLService,
|
|
545
|
-
Effect_exports.gen(function* () {
|
|
546
|
-
const poolsRef = yield* Ref_exports.make(/* @__PURE__ */ new Map());
|
|
547
|
-
yield* Effect_exports.addFinalizer(
|
|
548
|
-
() => Effect_exports.gen(function* () {
|
|
549
|
-
const pools = yield* Ref_exports.get(poolsRef);
|
|
550
|
-
for (const { pool } of pools.values()) {
|
|
551
|
-
yield* Effect_exports.tryPromise({
|
|
552
|
-
try: () => pool.end(),
|
|
553
|
-
catch: (cause) => new DBError({ db: "mysql", op: "shutdown end", cause })
|
|
554
|
-
}).pipe(Effect_exports.orElse(() => Effect_exports.void));
|
|
555
|
-
}
|
|
556
|
-
yield* Ref_exports.set(poolsRef, /* @__PURE__ */ new Map());
|
|
557
|
-
yield* Effect_exports.logInfo(
|
|
558
|
-
`[MySQLServiceLive] disposed ${pools.size} pool(s)`
|
|
559
|
-
);
|
|
560
|
-
})
|
|
561
|
-
);
|
|
562
|
-
return MySQLService.of({
|
|
563
|
-
query: (id, connStr, sql, params) => Effect_exports.gen(function* () {
|
|
564
|
-
const pool = yield* acquirePool2(poolsRef, id, connStr);
|
|
565
|
-
const [rows] = yield* handleAsync2(
|
|
566
|
-
"query",
|
|
567
|
-
() => pool.query(sql, params)
|
|
568
|
-
);
|
|
569
|
-
return rows;
|
|
570
|
-
}).pipe(Effect_exports.withSpan("mysql.query", { attributes: { id } })),
|
|
571
|
-
queryWithMeta: (id, connStr, sql, params) => Effect_exports.gen(function* () {
|
|
572
|
-
const pool = yield* acquirePool2(poolsRef, id, connStr);
|
|
573
|
-
const start = performance.now();
|
|
574
|
-
const [result, fieldPackets] = yield* handleAsync2(
|
|
575
|
-
"queryWithMeta",
|
|
576
|
-
() => pool.query(sql, params)
|
|
577
|
-
);
|
|
578
|
-
const duration = Math.round((performance.now() - start) * 100) / 100;
|
|
579
|
-
if (Array.isArray(result) && Array.isArray(fieldPackets)) {
|
|
580
|
-
const rows = result;
|
|
581
|
-
const fields = fieldPackets.map((f) => ({ name: f.name, dataTypeID: f.columnType ?? 0 }));
|
|
582
|
-
const meta2 = {
|
|
583
|
-
rows,
|
|
584
|
-
fields,
|
|
585
|
-
rowCount: rows.length,
|
|
586
|
-
command: null,
|
|
587
|
-
duration
|
|
588
|
-
};
|
|
589
|
-
return meta2;
|
|
590
|
-
}
|
|
591
|
-
const header = result;
|
|
592
|
-
const meta = {
|
|
593
|
-
rows: [],
|
|
594
|
-
fields: null,
|
|
595
|
-
rowCount: header.affectedRows ?? 0,
|
|
596
|
-
command: sql.trim().split(/\s+/)[0]?.toUpperCase() || "QUERY",
|
|
597
|
-
duration
|
|
598
|
-
};
|
|
599
|
-
return meta;
|
|
600
|
-
}).pipe(
|
|
601
|
-
Effect_exports.withSpan("mysql.queryWithMeta", { attributes: { id } })
|
|
602
|
-
),
|
|
603
|
-
withTx: (id, connStr, f) => Effect_exports.gen(function* () {
|
|
604
|
-
const pool = yield* acquirePool2(poolsRef, id, connStr);
|
|
605
|
-
const conn = yield* handleAsync2(
|
|
606
|
-
"getConnection",
|
|
607
|
-
() => pool.getConnection()
|
|
608
|
-
);
|
|
609
|
-
yield* handleAsync2("BEGIN", () => conn.beginTransaction());
|
|
610
|
-
const tx = {
|
|
611
|
-
query: (sql, params) => handleAsync2(
|
|
612
|
-
"tx.query",
|
|
613
|
-
() => conn.query(sql, params).then(([rows]) => rows)
|
|
614
|
-
)
|
|
615
|
-
};
|
|
616
|
-
const result = yield* f(tx).pipe(
|
|
617
|
-
Effect_exports.tapBoth({
|
|
618
|
-
onSuccess: () => handleAsync2("COMMIT", () => conn.commit()),
|
|
619
|
-
onFailure: () => handleAsync2("ROLLBACK", () => conn.rollback()).pipe(
|
|
620
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
621
|
-
)
|
|
622
|
-
}),
|
|
623
|
-
Effect_exports.ensuring(Effect_exports.sync(() => conn.release()))
|
|
624
|
-
);
|
|
625
|
-
return result;
|
|
626
|
-
}).pipe(Effect_exports.withSpan("mysql.withTx", { attributes: { id } })),
|
|
627
|
-
disconnect: (id) => disconnectPool2(poolsRef, id)
|
|
628
|
-
});
|
|
629
|
-
})
|
|
630
|
-
);
|
|
631
|
-
|
|
632
|
-
// packages/feature/console/src/effect/redisLive.ts
|
|
633
|
-
import Redis from "ioredis";
|
|
634
|
-
var handleAsync3 = (op, f) => Effect_exports.tryPromise({
|
|
635
|
-
try: f,
|
|
636
|
-
catch: (cause) => new DBError({ db: "redis", op, cause })
|
|
637
|
-
});
|
|
638
|
-
var acquireClient = (clientsRef, id, connectionString) => Effect_exports.gen(function* () {
|
|
639
|
-
const clients = yield* Ref_exports.get(clientsRef);
|
|
640
|
-
const existing = clients.get(id);
|
|
641
|
-
if (existing && existing.connectionString === connectionString) {
|
|
642
|
-
if (existing.client.status === "ready") return existing.client;
|
|
643
|
-
yield* handleAsync3("quit", () => existing.client.quit()).pipe(
|
|
644
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
645
|
-
);
|
|
646
|
-
} else if (existing) {
|
|
647
|
-
yield* handleAsync3("quit", () => existing.client.quit()).pipe(
|
|
648
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
649
|
-
);
|
|
650
|
-
}
|
|
651
|
-
const client = yield* handleAsync3("connect", async () => {
|
|
652
|
-
const c = new Redis(connectionString, {
|
|
653
|
-
lazyConnect: true,
|
|
654
|
-
connectTimeout: 1e4,
|
|
655
|
-
maxRetriesPerRequest: 1
|
|
656
|
-
});
|
|
657
|
-
await c.connect();
|
|
658
|
-
return c;
|
|
659
|
-
});
|
|
660
|
-
yield* Ref_exports.update(clientsRef, (m) => {
|
|
661
|
-
const next = new Map(m);
|
|
662
|
-
next.set(id, { client, connectionString, createdAt: Date.now() });
|
|
663
|
-
return next;
|
|
664
|
-
});
|
|
665
|
-
return client;
|
|
666
|
-
});
|
|
667
|
-
var disconnectClient = (clientsRef, id) => Effect_exports.gen(function* () {
|
|
668
|
-
const clients = yield* Ref_exports.get(clientsRef);
|
|
669
|
-
const managed = clients.get(id);
|
|
670
|
-
if (!managed) return;
|
|
671
|
-
yield* handleAsync3("disconnect", () => managed.client.quit()).pipe(
|
|
672
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
673
|
-
);
|
|
674
|
-
yield* Ref_exports.update(clientsRef, (m) => {
|
|
675
|
-
const next = new Map(m);
|
|
676
|
-
next.delete(id);
|
|
677
|
-
return next;
|
|
678
|
-
});
|
|
679
|
-
});
|
|
680
|
-
var subscribeStream = (connStr, pattern) => Stream_exports.unwrapScoped(
|
|
681
|
-
Effect_exports.gen(function* () {
|
|
682
|
-
const queue = yield* Queue_exports.unbounded();
|
|
683
|
-
const sub = yield* Effect_exports.acquireRelease(
|
|
684
|
-
handleAsync3("subscribeConnect", async () => {
|
|
685
|
-
const c = new Redis(connStr, {
|
|
686
|
-
lazyConnect: true,
|
|
687
|
-
connectTimeout: 1e4,
|
|
688
|
-
maxRetriesPerRequest: 1
|
|
689
|
-
});
|
|
690
|
-
await c.connect();
|
|
691
|
-
return c;
|
|
692
|
-
}),
|
|
693
|
-
(c) => Effect_exports.tryPromise({
|
|
694
|
-
try: () => c.quit(),
|
|
695
|
-
catch: () => new DBError({ db: "redis", op: "subscribeQuit", cause: null })
|
|
696
|
-
}).pipe(Effect_exports.orElse(() => Effect_exports.void))
|
|
697
|
-
);
|
|
698
|
-
const isPattern = pattern.includes("*") || pattern.includes("?");
|
|
699
|
-
yield* handleAsync3(
|
|
700
|
-
"psubscribe",
|
|
701
|
-
() => isPattern ? sub.psubscribe(pattern) : sub.subscribe(pattern)
|
|
702
|
-
);
|
|
703
|
-
sub.on(isPattern ? "pmessage" : "message", (...args) => {
|
|
704
|
-
const channel = isPattern ? args[1] : args[0];
|
|
705
|
-
const message = isPattern ? args[2] : args[1];
|
|
706
|
-
Effect_exports.runFork(Queue_exports.offer(queue, { channel, message }));
|
|
707
|
-
});
|
|
708
|
-
return Stream_exports.fromQueue(queue);
|
|
709
|
-
})
|
|
710
|
-
);
|
|
711
|
-
var RedisServiceLive = Layer_exports.scoped(
|
|
712
|
-
RedisService,
|
|
713
|
-
Effect_exports.gen(function* () {
|
|
714
|
-
const clientsRef = yield* Ref_exports.make(/* @__PURE__ */ new Map());
|
|
715
|
-
yield* Effect_exports.addFinalizer(
|
|
716
|
-
() => Effect_exports.gen(function* () {
|
|
717
|
-
const clients = yield* Ref_exports.get(clientsRef);
|
|
718
|
-
for (const { client } of clients.values()) {
|
|
719
|
-
yield* Effect_exports.tryPromise({
|
|
720
|
-
try: () => client.quit(),
|
|
721
|
-
catch: (cause) => new DBError({ db: "redis", op: "shutdown quit", cause })
|
|
722
|
-
}).pipe(Effect_exports.orElse(() => Effect_exports.void));
|
|
723
|
-
}
|
|
724
|
-
yield* Ref_exports.set(clientsRef, /* @__PURE__ */ new Map());
|
|
725
|
-
yield* Effect_exports.logInfo(
|
|
726
|
-
`[RedisServiceLive] disposed ${clients.size} client(s)`
|
|
727
|
-
);
|
|
728
|
-
})
|
|
729
|
-
);
|
|
730
|
-
return RedisService.of({
|
|
731
|
-
command: (id, connStr, cmd, args) => Effect_exports.gen(function* () {
|
|
732
|
-
const client = yield* acquireClient(clientsRef, id, connStr);
|
|
733
|
-
const result = yield* handleAsync3(
|
|
734
|
-
"call",
|
|
735
|
-
() => client.call(cmd, ...args ?? [])
|
|
736
|
-
);
|
|
737
|
-
return result;
|
|
738
|
-
}).pipe(Effect_exports.withSpan("redis.command", { attributes: { id, cmd } })),
|
|
739
|
-
subscribe: (_id, connStr, pattern) => subscribeStream(connStr, pattern),
|
|
740
|
-
disconnect: (id) => disconnectClient(clientsRef, id)
|
|
741
|
-
});
|
|
742
|
-
})
|
|
743
|
-
);
|
|
744
|
-
|
|
745
|
-
// packages/feature/console/src/effect/neo4jLive.ts
|
|
746
|
-
var handleAsync4 = (op, f) => Effect_exports.tryPromise({
|
|
747
|
-
try: f,
|
|
748
|
-
catch: (cause) => new DBError({ db: "neo4j", op, cause })
|
|
749
|
-
});
|
|
750
|
-
var acquireDriver = (driversRef, id, connectionString) => Effect_exports.gen(function* () {
|
|
751
|
-
const drivers = yield* Ref_exports.get(driversRef);
|
|
752
|
-
const existing = drivers.get(id);
|
|
753
|
-
if (existing && existing.connectionString === connectionString) {
|
|
754
|
-
return existing.driver;
|
|
755
|
-
}
|
|
756
|
-
if (existing) {
|
|
757
|
-
yield* handleAsync4("close", () => existing.driver.close()).pipe(
|
|
758
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
const driver = yield* handleAsync4(
|
|
762
|
-
"createDriver",
|
|
763
|
-
() => createNeo4jDriver(connectionString)
|
|
764
|
-
);
|
|
765
|
-
yield* Ref_exports.update(driversRef, (m) => {
|
|
766
|
-
const next = new Map(m);
|
|
767
|
-
next.set(id, { driver, connectionString, createdAt: Date.now() });
|
|
768
|
-
return next;
|
|
769
|
-
});
|
|
770
|
-
return driver;
|
|
771
|
-
});
|
|
772
|
-
var disconnectDriver = (driversRef, id) => Effect_exports.gen(function* () {
|
|
773
|
-
const drivers = yield* Ref_exports.get(driversRef);
|
|
774
|
-
const managed = drivers.get(id);
|
|
775
|
-
if (!managed) return;
|
|
776
|
-
yield* handleAsync4("disconnect", () => managed.driver.close()).pipe(
|
|
777
|
-
Effect_exports.orElse(() => Effect_exports.void)
|
|
778
|
-
);
|
|
779
|
-
yield* Ref_exports.update(driversRef, (m) => {
|
|
780
|
-
const next = new Map(m);
|
|
781
|
-
next.delete(id);
|
|
782
|
-
return next;
|
|
783
|
-
});
|
|
784
|
-
});
|
|
785
|
-
var Neo4jServiceLive = Layer_exports.scoped(
|
|
786
|
-
Neo4jService,
|
|
787
|
-
Effect_exports.gen(function* () {
|
|
788
|
-
const driversRef = yield* Ref_exports.make(/* @__PURE__ */ new Map());
|
|
789
|
-
yield* Effect_exports.addFinalizer(
|
|
790
|
-
() => Effect_exports.gen(function* () {
|
|
791
|
-
const drivers = yield* Ref_exports.get(driversRef);
|
|
792
|
-
for (const { driver } of drivers.values()) {
|
|
793
|
-
yield* Effect_exports.tryPromise({
|
|
794
|
-
try: () => driver.close(),
|
|
795
|
-
catch: (cause) => new DBError({ db: "neo4j", op: "shutdown close", cause })
|
|
796
|
-
}).pipe(Effect_exports.orElse(() => Effect_exports.void));
|
|
797
|
-
}
|
|
798
|
-
yield* Ref_exports.set(driversRef, /* @__PURE__ */ new Map());
|
|
799
|
-
yield* Effect_exports.logInfo(
|
|
800
|
-
`[Neo4jServiceLive] disposed ${drivers.size} driver(s)`
|
|
801
|
-
);
|
|
802
|
-
})
|
|
803
|
-
);
|
|
804
|
-
return Neo4jService.of({
|
|
805
|
-
run: (id, connStr, cypher, params) => Effect_exports.gen(function* () {
|
|
806
|
-
const driver = yield* acquireDriver(driversRef, id, connStr);
|
|
807
|
-
const result = yield* handleAsync4(
|
|
808
|
-
"run",
|
|
809
|
-
() => runCypherWithDriver(driver, cypher, params)
|
|
810
|
-
);
|
|
811
|
-
return result.records;
|
|
812
|
-
}).pipe(Effect_exports.withSpan("neo4j.run", { attributes: { id } })),
|
|
813
|
-
runWithMeta: (id, connStr, cypher, params) => Effect_exports.gen(function* () {
|
|
814
|
-
const driver = yield* acquireDriver(driversRef, id, connStr);
|
|
815
|
-
const result = yield* handleAsync4(
|
|
816
|
-
"runWithMeta",
|
|
817
|
-
() => runCypherWithDriver(driver, cypher, params)
|
|
818
|
-
);
|
|
819
|
-
const meta = {
|
|
820
|
-
records: result.records,
|
|
821
|
-
keys: result.keys,
|
|
822
|
-
duration: result.duration,
|
|
823
|
-
counters: result.counters
|
|
824
|
-
};
|
|
825
|
-
return meta;
|
|
826
|
-
}).pipe(
|
|
827
|
-
Effect_exports.withSpan("neo4j.runWithMeta", { attributes: { id } })
|
|
828
|
-
),
|
|
829
|
-
disconnect: (id) => disconnectDriver(driversRef, id)
|
|
830
|
-
});
|
|
831
|
-
})
|
|
832
|
-
);
|
|
833
|
-
|
|
834
|
-
// packages/feature/console/src/effect/mongoLive.ts
|
|
835
|
-
var notImpl = (op) => Effect_exports.fail(
|
|
836
|
-
new DBError({
|
|
837
|
-
db: "mongo",
|
|
838
|
-
op,
|
|
839
|
-
cause: new Error("MongoServiceLive not implemented (mongodb driver not installed)")
|
|
840
|
-
})
|
|
841
|
-
);
|
|
842
|
-
var MongoServiceLive = Layer_exports.succeed(
|
|
843
|
-
MongoService,
|
|
844
|
-
MongoService.of({
|
|
845
|
-
find: () => notImpl("find"),
|
|
846
|
-
command: () => notImpl("command"),
|
|
847
|
-
disconnect: () => Effect_exports.void
|
|
848
|
-
// No connection, disconnect is a no-op
|
|
849
|
-
})
|
|
850
|
-
);
|
|
851
|
-
|
|
852
|
-
// packages/feature/agent/src/effect/schedulerLive.ts
|
|
853
|
-
var SchedulerLive = Layer_exports.scoped(
|
|
854
|
-
Scheduler,
|
|
855
|
-
Effect_exports.gen(function* () {
|
|
856
|
-
const fibersRef = yield* Ref_exports.make(
|
|
857
|
-
/* @__PURE__ */ new Map()
|
|
858
|
-
);
|
|
859
|
-
yield* Effect_exports.addFinalizer(
|
|
860
|
-
() => Effect_exports.gen(function* () {
|
|
861
|
-
const fibers = yield* Ref_exports.get(fibersRef);
|
|
862
|
-
for (const f of fibers.values()) {
|
|
863
|
-
yield* Fiber_exports.interrupt(f);
|
|
864
|
-
}
|
|
865
|
-
yield* Ref_exports.set(fibersRef, /* @__PURE__ */ new Map());
|
|
866
|
-
})
|
|
867
|
-
);
|
|
868
|
-
return Scheduler.of({
|
|
869
|
-
schedule: (id, task, policy) => Effect_exports.gen(function* () {
|
|
870
|
-
const existing = yield* Ref_exports.get(fibersRef).pipe(
|
|
871
|
-
Effect_exports.map((m) => m.get(id))
|
|
872
|
-
);
|
|
873
|
-
if (existing) {
|
|
874
|
-
yield* Fiber_exports.interrupt(existing);
|
|
875
|
-
}
|
|
876
|
-
const fiber = yield* Effect_exports.forkScoped(
|
|
877
|
-
task.pipe(
|
|
878
|
-
Effect_exports.repeat(policy),
|
|
879
|
-
Effect_exports.tapError(
|
|
880
|
-
(e) => Effect_exports.logError(`[scheduler] task '${id}' failed`).pipe(
|
|
881
|
-
Effect_exports.annotateLogs("error", String(e))
|
|
882
|
-
)
|
|
883
|
-
)
|
|
884
|
-
)
|
|
885
|
-
);
|
|
886
|
-
yield* Ref_exports.update(
|
|
887
|
-
fibersRef,
|
|
888
|
-
(m) => new Map(m).set(id, fiber)
|
|
889
|
-
);
|
|
890
|
-
yield* Effect_exports.logInfo(`[scheduler] task '${id}' started`);
|
|
891
|
-
return { id, fiber };
|
|
892
|
-
}),
|
|
893
|
-
list: Effect_exports.gen(function* () {
|
|
894
|
-
const fibers = yield* Ref_exports.get(fibersRef);
|
|
895
|
-
return Array.from(fibers.keys());
|
|
896
|
-
}),
|
|
897
|
-
cancel: (id) => Effect_exports.gen(function* () {
|
|
898
|
-
const fibers = yield* Ref_exports.get(fibersRef);
|
|
899
|
-
const f = fibers.get(id);
|
|
900
|
-
if (f) {
|
|
901
|
-
yield* Fiber_exports.interrupt(f);
|
|
902
|
-
yield* Ref_exports.update(fibersRef, (m) => {
|
|
903
|
-
const next = new Map(m);
|
|
904
|
-
next.delete(id);
|
|
905
|
-
return next;
|
|
906
|
-
});
|
|
907
|
-
yield* Effect_exports.logInfo(`[scheduler] task '${id}' cancelled`);
|
|
908
|
-
}
|
|
909
|
-
})
|
|
910
|
-
});
|
|
911
|
-
})
|
|
912
|
-
);
|
|
913
|
-
|
|
914
|
-
// packages/feature/agent/src/effect/claudeSdkAdapter.ts
|
|
915
18
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
916
|
-
var providerEnvFor = (provider, apiKeyOverride) => {
|
|
917
|
-
switch (provider) {
|
|
918
|
-
case "claude":
|
|
919
|
-
return apiKeyOverride ? { apiKey: apiKeyOverride } : {};
|
|
920
|
-
case "codex":
|
|
921
|
-
return {
|
|
922
|
-
baseUrl: "https://api.openai.com/v1",
|
|
923
|
-
apiKey: apiKeyOverride
|
|
924
|
-
};
|
|
925
|
-
case "kimi":
|
|
926
|
-
return {
|
|
927
|
-
baseUrl: "https://api.moonshot.cn/anthropic",
|
|
928
|
-
apiKey: apiKeyOverride
|
|
929
|
-
};
|
|
930
|
-
case "deepseek":
|
|
931
|
-
return {
|
|
932
|
-
baseUrl: "https://api.deepseek.com/anthropic",
|
|
933
|
-
apiKey: apiKeyOverride
|
|
934
|
-
};
|
|
935
|
-
case "ollama":
|
|
936
|
-
return {};
|
|
937
|
-
}
|
|
938
|
-
};
|
|
939
|
-
var buildOptions = (req, apiKeyOverride) => {
|
|
940
|
-
const env = providerEnvFor(req.provider, apiKeyOverride);
|
|
941
|
-
return {
|
|
942
|
-
model: req.model,
|
|
943
|
-
env: {
|
|
944
|
-
...process.env,
|
|
945
|
-
...env.baseUrl ? { ANTHROPIC_BASE_URL: env.baseUrl } : {},
|
|
946
|
-
...env.apiKey ? { ANTHROPIC_API_KEY: env.apiKey } : {}
|
|
947
|
-
}
|
|
948
|
-
};
|
|
949
|
-
};
|
|
950
|
-
var messagesToPrompt = (req) => {
|
|
951
|
-
const last = [...req.messages].reverse().find((m) => m.role === "user");
|
|
952
|
-
return last?.content ?? "";
|
|
953
|
-
};
|
|
954
|
-
var claudeChat = (req, apiKeyOverride) => Effect_exports.gen(function* () {
|
|
955
|
-
const chunks = yield* Stream_exports.runCollect(claudeStream(req, apiKeyOverride));
|
|
956
|
-
let text = "";
|
|
957
|
-
let usage;
|
|
958
|
-
for (const c of chunks) {
|
|
959
|
-
if (c._tag === "text") text += c.delta;
|
|
960
|
-
else if (c._tag === "done") usage = c.usage;
|
|
961
|
-
}
|
|
962
|
-
return {
|
|
963
|
-
message: { role: "assistant", content: text },
|
|
964
|
-
usage
|
|
965
|
-
};
|
|
966
|
-
}).pipe(Effect_exports.withSpan("agent.chat", { attributes: { provider: req.provider, model: req.model } }));
|
|
967
|
-
var claudeStream = (req, apiKeyOverride) => Stream_exports.async((emit) => {
|
|
968
|
-
const provider = req.provider;
|
|
969
|
-
const options = buildOptions(req, apiKeyOverride);
|
|
970
|
-
const prompt = messagesToPrompt(req);
|
|
971
|
-
let cancelled = false;
|
|
972
|
-
void (async () => {
|
|
973
|
-
try {
|
|
974
|
-
const response = query({ prompt, options });
|
|
975
|
-
for await (const message of response) {
|
|
976
|
-
if (cancelled) break;
|
|
977
|
-
const msg = message;
|
|
978
|
-
if (msg.type === "assistant" && msg.message?.content) {
|
|
979
|
-
for (const block of msg.message.content) {
|
|
980
|
-
if (block.type === "text" && block.text) {
|
|
981
|
-
void emit.single({ _tag: "text", delta: block.text });
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
if (msg.type === "result") {
|
|
986
|
-
void emit.single({
|
|
987
|
-
_tag: "done",
|
|
988
|
-
usage: msg.usage ? {
|
|
989
|
-
inputTokens: msg.usage.input_tokens ?? 0,
|
|
990
|
-
outputTokens: msg.usage.output_tokens ?? 0
|
|
991
|
-
} : void 0
|
|
992
|
-
});
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
void emit.end();
|
|
996
|
-
} catch (cause) {
|
|
997
|
-
void emit.fail(
|
|
998
|
-
new AgentError({
|
|
999
|
-
provider,
|
|
1000
|
-
kind: "protocol",
|
|
1001
|
-
cause
|
|
1002
|
-
})
|
|
1003
|
-
);
|
|
1004
|
-
}
|
|
1005
|
-
})();
|
|
1006
|
-
return Effect_exports.sync(() => {
|
|
1007
|
-
cancelled = true;
|
|
1008
|
-
});
|
|
1009
|
-
});
|
|
1010
|
-
|
|
1011
|
-
// packages/feature/agent/src/effect/ollamaAdapter.ts
|
|
1012
|
-
import { streamText } from "ai";
|
|
1013
|
-
|
|
1014
|
-
// packages/feature/agent/src/server/api/chat/ollama/model.ts
|
|
1015
|
-
import { createOpenAI } from "@ai-sdk/openai";
|
|
1016
|
-
var ollamaFetch = async (input, init) => {
|
|
1017
|
-
if (init && typeof init.body === "string") {
|
|
1018
|
-
try {
|
|
1019
|
-
const body = JSON.parse(init.body);
|
|
1020
|
-
if (Array.isArray(body.messages)) {
|
|
1021
|
-
let mutated = false;
|
|
1022
|
-
for (const m of body.messages) {
|
|
1023
|
-
if (m && m.role === "assistant" && m.content == null) {
|
|
1024
|
-
m.content = "";
|
|
1025
|
-
mutated = true;
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
if (mutated) init = { ...init, body: JSON.stringify(body) };
|
|
1029
|
-
}
|
|
1030
|
-
} catch {
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
return fetch(input, init);
|
|
1034
|
-
};
|
|
1035
|
-
function createOllamaModel(modelName) {
|
|
1036
|
-
const provider = createOpenAI({
|
|
1037
|
-
// EFFECT.md §0 exemption: third-party plugin API key in the same category as
|
|
1038
|
-
// OPENAI_API_KEY / ANTHROPIC_API_KEY; not pulled into CockpitConfig (would over-couple
|
|
1039
|
-
// cockpit configuration with third-party authentication).
|
|
1040
|
-
apiKey: process.env.OLLAMA_API_KEY || "ollama",
|
|
1041
|
-
baseURL: getOllamaOpenAIBaseURL(),
|
|
1042
|
-
fetch: ollamaFetch
|
|
1043
|
-
});
|
|
1044
|
-
return provider.chat(modelName);
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// packages/feature/agent/src/effect/ollamaAdapter.ts
|
|
1048
|
-
var toModelMessages = (messages) => messages.map((m) => ({
|
|
1049
|
-
role: m.role,
|
|
1050
|
-
content: m.content
|
|
1051
|
-
}));
|
|
1052
|
-
var ollamaChat = (req) => Effect_exports.gen(function* () {
|
|
1053
|
-
const chunks = yield* Stream_exports.runCollect(ollamaStream(req));
|
|
1054
|
-
let text = "";
|
|
1055
|
-
let usage;
|
|
1056
|
-
for (const c of chunks) {
|
|
1057
|
-
if (c._tag === "text") text += c.delta;
|
|
1058
|
-
else if (c._tag === "done") usage = c.usage;
|
|
1059
|
-
}
|
|
1060
|
-
return {
|
|
1061
|
-
message: { role: "assistant", content: text },
|
|
1062
|
-
usage
|
|
1063
|
-
};
|
|
1064
|
-
}).pipe(Effect_exports.withSpan("agent.chat", { attributes: { provider: "ollama", model: req.model } }));
|
|
1065
|
-
var ollamaStream = (req) => Stream_exports.async((emit) => {
|
|
1066
|
-
const abortController = new AbortController();
|
|
1067
|
-
void (async () => {
|
|
1068
|
-
try {
|
|
1069
|
-
const ollamaModel = createOllamaModel(req.model);
|
|
1070
|
-
const result = streamText({
|
|
1071
|
-
model: ollamaModel,
|
|
1072
|
-
messages: toModelMessages(req.messages),
|
|
1073
|
-
temperature: req.temperature ?? 0,
|
|
1074
|
-
abortSignal: abortController.signal
|
|
1075
|
-
});
|
|
1076
|
-
for await (const part of result.fullStream) {
|
|
1077
|
-
if (part.type === "text-delta") {
|
|
1078
|
-
const delta = part.text;
|
|
1079
|
-
if (delta) void emit.single({ _tag: "text", delta });
|
|
1080
|
-
} else if (part.type === "finish") {
|
|
1081
|
-
const u = part.totalUsage;
|
|
1082
|
-
void emit.single({
|
|
1083
|
-
_tag: "done",
|
|
1084
|
-
usage: u ? { inputTokens: u.inputTokens ?? 0, outputTokens: u.outputTokens ?? 0 } : void 0
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
void emit.end();
|
|
1089
|
-
} catch (cause) {
|
|
1090
|
-
void emit.fail(
|
|
1091
|
-
new AgentError({ provider: "ollama", kind: "protocol", cause })
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
|
-
})();
|
|
1095
|
-
return Effect_exports.sync(() => abortController.abort());
|
|
1096
|
-
});
|
|
1097
|
-
|
|
1098
|
-
// packages/feature/agent/src/effect/agentLive.ts
|
|
1099
|
-
var retryableKinds = /* @__PURE__ */ new Set([
|
|
1100
|
-
"rate-limit",
|
|
1101
|
-
"timeout",
|
|
1102
|
-
"unknown"
|
|
1103
|
-
]);
|
|
1104
|
-
var isRetryable = (e) => retryableKinds.has(e.kind);
|
|
1105
|
-
var withAgentRetry = (effect) => effect.pipe(
|
|
1106
|
-
Effect_exports.retry({
|
|
1107
|
-
schedule: agentRetry,
|
|
1108
|
-
while: (e) => isRetryable(e)
|
|
1109
|
-
})
|
|
1110
|
-
);
|
|
1111
|
-
var dispatchChat = (req) => {
|
|
1112
|
-
switch (req.provider) {
|
|
1113
|
-
case "ollama":
|
|
1114
|
-
return ollamaChat(req);
|
|
1115
|
-
case "claude":
|
|
1116
|
-
case "codex":
|
|
1117
|
-
case "kimi":
|
|
1118
|
-
case "deepseek":
|
|
1119
|
-
return claudeChat(req);
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1122
|
-
var dispatchStream = (req) => {
|
|
1123
|
-
switch (req.provider) {
|
|
1124
|
-
case "ollama":
|
|
1125
|
-
return ollamaStream(req);
|
|
1126
|
-
case "claude":
|
|
1127
|
-
case "codex":
|
|
1128
|
-
case "kimi":
|
|
1129
|
-
case "deepseek":
|
|
1130
|
-
return claudeStream(req);
|
|
1131
|
-
}
|
|
1132
|
-
};
|
|
1133
|
-
var AgentServiceLive = Layer_exports.succeed(
|
|
1134
|
-
AgentService,
|
|
1135
|
-
AgentService.of({
|
|
1136
|
-
chat: (req) => withAgentRetry(dispatchChat(req)),
|
|
1137
|
-
stream: (req) => dispatchStream(req)
|
|
1138
|
-
// Streaming is excluded from retry (mid-stream retry would drop already-emitted content)
|
|
1139
|
-
})
|
|
1140
|
-
);
|
|
1141
|
-
|
|
1142
|
-
// packages/shared/effect-runtime/src/server/runtime.ts
|
|
1143
|
-
var isDev = process.env.COCKPIT_ENV === "dev";
|
|
1144
|
-
var ServerBaseLayer = Layer_exports.unwrapEffect(
|
|
1145
|
-
Effect_exports.gen(function* () {
|
|
1146
|
-
const cfg = yield* CockpitConfig;
|
|
1147
|
-
const loggerLayer = isDev ? LoggerLivePretty : LoggerLiveProd(cfg.logFile);
|
|
1148
|
-
const tracerLayer = isDev ? TracerLivePretty : TracerLiveNoop;
|
|
1149
|
-
return Layer_exports.mergeAll(loggerLayer, tracerLayer, ConfigLive);
|
|
1150
|
-
})
|
|
1151
|
-
);
|
|
1152
|
-
var AppLayer = Layer_exports.mergeAll(
|
|
1153
|
-
ServerBaseLayer,
|
|
1154
|
-
// DB services
|
|
1155
|
-
PgServiceLive,
|
|
1156
|
-
MySQLServiceLive,
|
|
1157
|
-
RedisServiceLive,
|
|
1158
|
-
Neo4jServiceLive,
|
|
1159
|
-
MongoServiceLive,
|
|
1160
|
-
// Scheduler
|
|
1161
|
-
SchedulerLive,
|
|
1162
|
-
// Agent
|
|
1163
|
-
AgentServiceLive
|
|
1164
|
-
);
|
|
1165
|
-
var AppRuntime = ManagedRuntime_exports.make(AppLayer);
|
|
1166
|
-
|
|
1167
|
-
// packages/feature/agent/src/server/scheduledTasks.ts
|
|
1168
19
|
function parseCronField(field, min, max) {
|
|
1169
20
|
const values = [];
|
|
1170
21
|
for (const part of field.split(",")) {
|
|
@@ -1224,7 +75,12 @@ var sendChatMessageEff = (task) => {
|
|
|
1224
75
|
"WebFetch",
|
|
1225
76
|
"WebSearch",
|
|
1226
77
|
"Task",
|
|
1227
|
-
|
|
78
|
+
// Task management — claude-agent-sdk@0.3.142 replaced TodoWrite
|
|
79
|
+
// with per-task TaskCreate/Update/Get/List events.
|
|
80
|
+
"TaskCreate",
|
|
81
|
+
"TaskUpdate",
|
|
82
|
+
"TaskGet",
|
|
83
|
+
"TaskList",
|
|
1228
84
|
"mcp__*"
|
|
1229
85
|
],
|
|
1230
86
|
permissionMode: "bypassPermissions",
|
|
@@ -1243,7 +99,7 @@ var sendChatMessageEff = (task) => {
|
|
|
1243
99
|
try: async () => {
|
|
1244
100
|
for (let attempt = 0; attempt <= MAX_COMPACTION_RETRIES; attempt++) {
|
|
1245
101
|
let receivedResult = false;
|
|
1246
|
-
const response =
|
|
102
|
+
const response = query({
|
|
1247
103
|
prompt: attempt === 0 ? task.message : "continue",
|
|
1248
104
|
options
|
|
1249
105
|
});
|
|
@@ -1639,8 +495,8 @@ var ScheduledTaskManager = class {
|
|
|
1639
495
|
}
|
|
1640
496
|
}
|
|
1641
497
|
};
|
|
1642
|
-
var
|
|
1643
|
-
var scheduledTaskManager =
|
|
498
|
+
var g = globalThis;
|
|
499
|
+
var scheduledTaskManager = g.__scheduledTaskManager ?? (g.__scheduledTaskManager = new ScheduledTaskManager());
|
|
1644
500
|
export {
|
|
1645
501
|
getNextCronTime,
|
|
1646
502
|
scheduledTaskManager,
|