@skein-js/server-kit 0.11.2 → 0.12.0
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/README.md +31 -3
- package/dist/chunk-JUBBCC7R.js +56 -0
- package/dist/chunk-QOHYARHD.js +237 -0
- package/dist/dev-BfYYRfEB.d.ts +46 -0
- package/dist/dev.d.ts +4 -0
- package/dist/dev.js +303 -0
- package/dist/in-memory-runtime-32UYJRVJ.js +9 -0
- package/dist/index.d.ts +325 -45
- package/dist/index.js +323 -496
- package/package.json +10 -5
package/dist/index.js
CHANGED
|
@@ -1,225 +1,139 @@
|
|
|
1
|
-
// src/resolve-runtime.ts
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
corsFromHttpConfig,
|
|
3
|
+
createInMemoryDeps,
|
|
4
|
+
disabledRoutesFromHttpConfig,
|
|
5
|
+
embedInMemoryGraphs,
|
|
6
|
+
graphMapToResolver,
|
|
7
|
+
loadInMemoryRuntime,
|
|
8
|
+
loadReloadableInMemoryRuntime,
|
|
9
|
+
normalizeEmbeddableGraphs,
|
|
10
|
+
positiveIntegerFromEnv,
|
|
11
|
+
requirePositiveInteger,
|
|
12
|
+
resolveMaxPageSize,
|
|
13
|
+
resolveMemoryBusLimits,
|
|
14
|
+
routesFromHttpConfig,
|
|
15
|
+
toCorsOptions
|
|
16
|
+
} from "./chunk-QOHYARHD.js";
|
|
17
|
+
import "./chunk-JUBBCC7R.js";
|
|
5
18
|
|
|
6
|
-
// src/
|
|
7
|
-
import { MemorySaver as MemorySaver2 } from "@langchain/langgraph";
|
|
19
|
+
// src/resolve-runtime.ts
|
|
8
20
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "@skein-js/
|
|
12
|
-
import { MemoryRunEventBus as MemoryRunEventBus2, MemoryRunQueue as MemoryRunQueue2, MemorySkeinStore as MemorySkeinStore2 } from "@skein-js/storage-memory";
|
|
21
|
+
createProtocolRuntime,
|
|
22
|
+
skeinRoutes
|
|
23
|
+
} from "@skein-js/agent-protocol";
|
|
13
24
|
|
|
14
|
-
// src/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
const listed = allowAll ? void 0 : new Set(config.allow_origins);
|
|
22
|
-
options.origin = (origin, callback) => callback(
|
|
23
|
-
null,
|
|
24
|
-
origin !== void 0 && (allowAll || pattern.test(origin) || (listed?.has(origin) ?? false))
|
|
25
|
-
);
|
|
26
|
-
} else if (config.allow_origins !== void 0) {
|
|
27
|
-
options.origin = allowAll ? "*" : config.allow_origins;
|
|
28
|
-
}
|
|
29
|
-
if (config.allow_methods !== void 0) options.methods = config.allow_methods;
|
|
30
|
-
if (config.allow_headers !== void 0) options.allowedHeaders = config.allow_headers;
|
|
31
|
-
if (config.allow_credentials !== void 0) options.credentials = config.allow_credentials;
|
|
32
|
-
if (config.max_age !== void 0) options.maxAge = config.max_age;
|
|
33
|
-
const exposed = /* @__PURE__ */ new Set([...ALWAYS_EXPOSED_HEADERS, ...config.expose_headers ?? []]);
|
|
34
|
-
options.exposedHeaders = [...exposed];
|
|
35
|
-
return options;
|
|
36
|
-
}
|
|
37
|
-
function corsFromHttpConfig(http) {
|
|
38
|
-
if (typeof http !== "object" || http === null) return void 0;
|
|
39
|
-
const cors = http.cors;
|
|
40
|
-
if (typeof cors !== "object" || cors === null) return void 0;
|
|
41
|
-
return toCorsOptions(cors);
|
|
25
|
+
// src/cron-tick.ts
|
|
26
|
+
import { DEFAULT_CRON_TICK_MS } from "@skein-js/agent-protocol";
|
|
27
|
+
var CRON_TICK_ENV_VARS = ["SKEIN_CRON_TICK_MS"];
|
|
28
|
+
function resolveCronTickMs(explicit, env = process.env) {
|
|
29
|
+
const fromEnv = positiveIntegerFromEnv(CRON_TICK_ENV_VARS, env);
|
|
30
|
+
if (explicit === void 0) return fromEnv ?? DEFAULT_CRON_TICK_MS;
|
|
31
|
+
return requirePositiveInteger("scheduler.tickMs", explicit);
|
|
42
32
|
}
|
|
43
33
|
|
|
44
|
-
// src/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
taskId,
|
|
90
|
-
channel,
|
|
91
|
-
fromBase64(blob)
|
|
92
|
-
])
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/in-memory-deps.ts
|
|
97
|
-
import { MemorySaver } from "@langchain/langgraph";
|
|
98
|
-
import { MemoryRunEventBus, MemoryRunQueue, MemorySkeinStore } from "@skein-js/storage-memory";
|
|
99
|
-
function isGraphResolver(graphs) {
|
|
100
|
-
const candidate = graphs;
|
|
101
|
-
return Array.isArray(candidate.ids) && typeof candidate.load === "function";
|
|
102
|
-
}
|
|
103
|
-
function normalizeEmbeddableGraphs(graphs) {
|
|
104
|
-
return isGraphResolver(graphs) ? graphs : graphMapToResolver(graphs);
|
|
105
|
-
}
|
|
106
|
-
function graphMapToResolver(graphs) {
|
|
107
|
-
const ids = Object.keys(graphs);
|
|
108
|
-
return {
|
|
109
|
-
ids,
|
|
110
|
-
load: async (graphId) => {
|
|
111
|
-
const graph = graphs[graphId];
|
|
112
|
-
if (graph == null) {
|
|
113
|
-
const known = ids.join(", ") || "none";
|
|
114
|
-
throw new Error(
|
|
115
|
-
ids.includes(graphId) ? `Graph "${graphId}" resolved to ${String(graph)} \u2014 check its export/factory (known: ${known}).` : `Unknown graph "${graphId}" (known: ${known}).`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
return graph;
|
|
119
|
-
},
|
|
120
|
-
schemas: async (graphId) => ({ [graphId]: { graph_id: graphId } })
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
function embedInMemoryGraphs(graphs, overrides = {}) {
|
|
124
|
-
return {
|
|
125
|
-
store: new MemorySkeinStore(),
|
|
126
|
-
graphs: normalizeEmbeddableGraphs(graphs),
|
|
127
|
-
queue: new MemoryRunQueue(),
|
|
128
|
-
bus: new MemoryRunEventBus(),
|
|
129
|
-
checkpointer: new MemorySaver(),
|
|
130
|
-
...overrides
|
|
34
|
+
// src/heap-pressure.ts
|
|
35
|
+
import { getHeapStatistics } from "v8";
|
|
36
|
+
import { SkeinConfigError } from "@skein-js/config/errors";
|
|
37
|
+
var DEFAULT_HEAP_WARN_PERCENT = 85;
|
|
38
|
+
var HEAP_REARM_MARGIN_PERCENT = 15;
|
|
39
|
+
var HEAP_REARM_PERCENT = DEFAULT_HEAP_WARN_PERCENT - HEAP_REARM_MARGIN_PERCENT;
|
|
40
|
+
var DEFAULT_HEAP_SAMPLE_MS = 3e4;
|
|
41
|
+
function megabytes(bytes) {
|
|
42
|
+
return `${Math.round(bytes / 1048576)}MB`;
|
|
43
|
+
}
|
|
44
|
+
function startHeapPressureMonitor(options = {}) {
|
|
45
|
+
const {
|
|
46
|
+
logger,
|
|
47
|
+
warnPercent = DEFAULT_HEAP_WARN_PERCENT,
|
|
48
|
+
sampleMs = DEFAULT_HEAP_SAMPLE_MS,
|
|
49
|
+
context,
|
|
50
|
+
heapStatistics = getHeapStatistics,
|
|
51
|
+
rss = () => process.memoryUsage().rss,
|
|
52
|
+
setInterval: schedule = (callback, ms) => setInterval(callback, ms),
|
|
53
|
+
clearInterval: unschedule = (handle2) => clearInterval(handle2)
|
|
54
|
+
} = options;
|
|
55
|
+
if (!logger || warnPercent <= 0 || sampleMs <= 0) return { stop: () => {
|
|
56
|
+
} };
|
|
57
|
+
const rearmPercent = Math.max(0, warnPercent - HEAP_REARM_MARGIN_PERCENT);
|
|
58
|
+
let warned = false;
|
|
59
|
+
const sample = () => {
|
|
60
|
+
const { heap_size_limit: limit, used_heap_size: used } = heapStatistics();
|
|
61
|
+
if (limit <= 0) return;
|
|
62
|
+
const percent = used / limit * 100;
|
|
63
|
+
if (warned) {
|
|
64
|
+
if (percent < rearmPercent) warned = false;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (percent < warnPercent) return;
|
|
68
|
+
warned = true;
|
|
69
|
+
const extra = context?.() ?? {};
|
|
70
|
+
const details = [
|
|
71
|
+
`heap ${megabytes(used)}/${megabytes(limit)} (${Math.round(percent)}%)`,
|
|
72
|
+
`rss ${megabytes(rss())}`,
|
|
73
|
+
extra.inFlightRuns !== void 0 ? `runs in flight ${extra.inFlightRuns}` : void 0,
|
|
74
|
+
extra.bufferedFrames !== void 0 ? `buffered frames ${extra.bufferedFrames}` : void 0
|
|
75
|
+
].filter(Boolean);
|
|
76
|
+
logger.warn?.(
|
|
77
|
+
`skein: heap pressure \u2014 ${details.join(", ")}. Many runs in flight suggests lowering SKEIN_RUN_CONCURRENCY; a large buffered-frame count suggests a slow SSE consumer (see SKEIN_MEMORY_BUS_MAX_FRAMES_PER_RUN); neither suggests a leak. Next warning only after usage drops below ${rearmPercent}%.`
|
|
78
|
+
);
|
|
131
79
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// src/in-memory-runtime.ts
|
|
136
|
-
function toGraphResolver(graphs) {
|
|
80
|
+
const handle = schedule(sample, sampleMs);
|
|
81
|
+
handle.unref?.();
|
|
82
|
+
let stopped = false;
|
|
137
83
|
return {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
84
|
+
stop() {
|
|
85
|
+
if (stopped) return;
|
|
86
|
+
stopped = true;
|
|
87
|
+
unschedule(handle);
|
|
88
|
+
}
|
|
141
89
|
};
|
|
142
90
|
}
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
importModule,
|
|
147
|
-
staticSchemas
|
|
148
|
-
});
|
|
149
|
-
const deps = embedInMemoryGraphs(toGraphResolver(graphs));
|
|
150
|
-
deps.auth = await loadAuthEngine(config.auth, { configDir, importModule });
|
|
91
|
+
function resolveHeapPressureOptions(explicit = {}, env = process.env) {
|
|
92
|
+
const warnFromEnv = percentFromEnv(env["SKEIN_HEAP_WARN_PERCENT"]);
|
|
93
|
+
const sampleFromEnv = positiveIntegerFromEnv(["SKEIN_HEAP_SAMPLE_MS"], env);
|
|
151
94
|
return {
|
|
152
|
-
|
|
153
|
-
|
|
95
|
+
warnPercent: explicit.warnPercent ?? warnFromEnv ?? DEFAULT_HEAP_WARN_PERCENT,
|
|
96
|
+
sampleMs: explicit.sampleMs ?? sampleFromEnv ?? DEFAULT_HEAP_SAMPLE_MS
|
|
154
97
|
};
|
|
155
98
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const checkpointer = new MemorySaver2();
|
|
166
|
-
const deps = {
|
|
167
|
-
store,
|
|
168
|
-
graphs,
|
|
169
|
-
queue: new MemoryRunQueue2(),
|
|
170
|
-
bus: new MemoryRunEventBus2(),
|
|
171
|
-
checkpointer,
|
|
172
|
-
auth: await loadAuthEngine(first.config.auth, { configDir: first.configDir, importModule }),
|
|
173
|
-
...extraDeps
|
|
174
|
-
};
|
|
175
|
-
return {
|
|
176
|
-
deps,
|
|
177
|
-
cors: corsFromHttpConfig(first.config.http),
|
|
178
|
-
config: first.config,
|
|
179
|
-
configDir: first.configDir,
|
|
180
|
-
reloadGraphs: async () => {
|
|
181
|
-
current = (await loadConfig({ configPath, importModule, staticSchemas })).graphs;
|
|
182
|
-
},
|
|
183
|
-
snapshotState: () => ({
|
|
184
|
-
version: 1,
|
|
185
|
-
store: store.snapshot(),
|
|
186
|
-
checkpoints: snapshotCheckpointer(checkpointer)
|
|
187
|
-
}),
|
|
188
|
-
hydrateState: (snapshot) => {
|
|
189
|
-
store.hydrate(snapshot.store);
|
|
190
|
-
hydrateCheckpointer(checkpointer, snapshot.checkpoints);
|
|
191
|
-
}
|
|
192
|
-
};
|
|
99
|
+
function percentFromEnv(raw) {
|
|
100
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
101
|
+
const value = Number(raw);
|
|
102
|
+
if (!Number.isInteger(value) || value < 0 || value > 100) {
|
|
103
|
+
throw new SkeinConfigError(
|
|
104
|
+
`SKEIN_HEAP_WARN_PERCENT must be an integer between 0 and 100 (got "${raw}").`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return value;
|
|
193
108
|
}
|
|
194
109
|
|
|
195
110
|
// src/run-concurrency.ts
|
|
196
111
|
import { DEFAULT_RUN_CONCURRENCY } from "@skein-js/agent-protocol";
|
|
197
|
-
|
|
112
|
+
var PG_DEFAULT_POOL_MAX = 10;
|
|
198
113
|
var CONCURRENCY_ENV_VARS = ["SKEIN_RUN_CONCURRENCY", "N_JOBS_PER_WORKER"];
|
|
199
|
-
function requirePositiveInteger(source, raw) {
|
|
200
|
-
const parsed = Number(raw);
|
|
201
|
-
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
202
|
-
throw new SkeinConfigError(`${source} must be a positive integer (got "${String(raw)}").`);
|
|
203
|
-
}
|
|
204
|
-
return parsed;
|
|
205
|
-
}
|
|
206
|
-
function runConcurrencyFromEnv(env) {
|
|
207
|
-
for (const name of CONCURRENCY_ENV_VARS) {
|
|
208
|
-
const raw = env[name];
|
|
209
|
-
if (raw === void 0 || raw.trim() === "") continue;
|
|
210
|
-
return requirePositiveInteger(name, raw);
|
|
211
|
-
}
|
|
212
|
-
return void 0;
|
|
213
|
-
}
|
|
214
114
|
function resolveRunConcurrency(explicit, env = process.env) {
|
|
215
|
-
const fromEnv =
|
|
115
|
+
const fromEnv = positiveIntegerFromEnv(CONCURRENCY_ENV_VARS, env);
|
|
216
116
|
if (explicit === void 0) return fromEnv ?? DEFAULT_RUN_CONCURRENCY;
|
|
217
117
|
return requirePositiveInteger("worker.maxConcurrency", explicit);
|
|
218
118
|
}
|
|
119
|
+
function describePoolPressure(runConcurrency, poolMax) {
|
|
120
|
+
const effectivePoolMax = poolMax ?? PG_DEFAULT_POOL_MAX;
|
|
121
|
+
if (runConcurrency <= effectivePoolMax) return void 0;
|
|
122
|
+
const source = poolMax === void 0 ? `pg's default of ${PG_DEFAULT_POOL_MAX}` : `PG_POOL_MAX`;
|
|
123
|
+
return `Run concurrency (${runConcurrency}) is higher than the Postgres pool allows (${effectivePoolMax}, from ${source}). Runs will queue waiting for a connection rather than executing, which looks like flat throughput rather than like a pool limit. Raise PG_POOL_MAX to at least ${runConcurrency}, or lower SKEIN_RUN_CONCURRENCY. Note skein opens two pools per instance (store + checkpointer), so budget ${runConcurrency * 2} connections against your database's own cap.`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/run-timeout.ts
|
|
127
|
+
var RUN_TIMEOUT_ENV_VARS = ["SKEIN_RUN_TIMEOUT_MS"];
|
|
128
|
+
function resolveRunTimeoutMs(explicit, env = process.env) {
|
|
129
|
+
const fromEnv = positiveIntegerFromEnv(RUN_TIMEOUT_ENV_VARS, env);
|
|
130
|
+
if (explicit === void 0) return fromEnv;
|
|
131
|
+
return requirePositiveInteger("runTimeoutMs", explicit);
|
|
132
|
+
}
|
|
219
133
|
|
|
220
134
|
// src/shutdown-grace.ts
|
|
221
135
|
import { DEFAULT_SHUTDOWN_GRACE_MS } from "@skein-js/agent-protocol";
|
|
222
|
-
import { SkeinConfigError as SkeinConfigError2 } from "@skein-js/config";
|
|
136
|
+
import { SkeinConfigError as SkeinConfigError2 } from "@skein-js/config/errors";
|
|
223
137
|
var SHUTDOWN_GRACE_ENV_VAR = "SKEIN_SHUTDOWN_GRACE_MS";
|
|
224
138
|
function requireNonNegativeInteger(source, raw) {
|
|
225
139
|
const parsed = Number(raw);
|
|
@@ -248,18 +162,33 @@ function resolveLogger(option, injected, frameworkLogger) {
|
|
|
248
162
|
return option ?? frameworkLogger;
|
|
249
163
|
}
|
|
250
164
|
async function resolveRuntimeDeps(options, frameworkLogger) {
|
|
251
|
-
const loaded = options.deps ? { deps: options.deps, cors: void 0 } : await loadInMemoryRuntime(options.config, options.importModule);
|
|
165
|
+
const loaded = options.deps ? { deps: options.deps, cors: void 0, routes: skeinRoutes } : await (await import("./in-memory-runtime-32UYJRVJ.js")).loadInMemoryRuntime(options.config, options.importModule);
|
|
252
166
|
const logger = resolveLogger(options.logger, loaded.deps.logger, frameworkLogger);
|
|
253
167
|
if (logger && !loaded.deps.logger) loaded.deps.logger = logger;
|
|
254
|
-
return { deps: loaded.deps, cors: loaded.cors, logger };
|
|
168
|
+
return { deps: loaded.deps, cors: loaded.cors, routes: loaded.routes, logger };
|
|
255
169
|
}
|
|
256
170
|
async function resolveProtocolRuntime(options, frameworkLogger) {
|
|
257
|
-
const {
|
|
171
|
+
const {
|
|
172
|
+
deps,
|
|
173
|
+
cors: corsFromConfig,
|
|
174
|
+
routes,
|
|
175
|
+
logger
|
|
176
|
+
} = await resolveRuntimeDeps(options, frameworkLogger);
|
|
177
|
+
const heapPressureOptions = resolveHeapPressureOptions();
|
|
178
|
+
const runTimeoutMs = resolveRunTimeoutMs(deps.runTimeoutMs);
|
|
179
|
+
if (runTimeoutMs !== void 0) deps.runTimeoutMs = runTimeoutMs;
|
|
258
180
|
const runtime = createProtocolRuntime(deps, {
|
|
259
181
|
worker: {
|
|
260
182
|
...options.worker,
|
|
261
183
|
maxConcurrency: resolveRunConcurrency(options.worker?.maxConcurrency),
|
|
262
184
|
shutdownGraceMs: resolveShutdownGraceMs(options.worker?.shutdownGraceMs)
|
|
185
|
+
},
|
|
186
|
+
scheduler: {
|
|
187
|
+
...options.scheduler,
|
|
188
|
+
tickMs: resolveCronTickMs(options.scheduler?.tickMs),
|
|
189
|
+
// `http.disable_crons` takes the whole resource away, so the scheduler goes with it: leaving
|
|
190
|
+
// it ticking would keep firing schedules nobody can see, list, or cancel any more.
|
|
191
|
+
enabled: options.scheduler?.enabled ?? routes.some((route) => route.group === "crons")
|
|
263
192
|
}
|
|
264
193
|
});
|
|
265
194
|
await runtime.service.assistants.registerGraphAssistants();
|
|
@@ -273,7 +202,31 @@ async function resolveProtocolRuntime(options, frameworkLogger) {
|
|
|
273
202
|
);
|
|
274
203
|
}
|
|
275
204
|
runtime.worker.start();
|
|
276
|
-
|
|
205
|
+
const heapMonitor = startHeapPressureMonitor({
|
|
206
|
+
...logger ? { logger } : {},
|
|
207
|
+
...heapPressureOptions,
|
|
208
|
+
// Read at warn time only. `bufferedFrameCount` is a diagnostic the in-memory bus exposes and the
|
|
209
|
+
// Redis one does not, so it is probed rather than required — on Redis the frames are not in this
|
|
210
|
+
// process's heap anyway, which is itself part of the answer.
|
|
211
|
+
context: () => {
|
|
212
|
+
const bufferedFrames = deps.bus.bufferedFrameCount;
|
|
213
|
+
return {
|
|
214
|
+
inFlightRuns: runtime.worker.inFlightRunCount,
|
|
215
|
+
...typeof bufferedFrames === "number" ? { bufferedFrames } : {}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
const worker = {
|
|
220
|
+
get inFlightRunCount() {
|
|
221
|
+
return runtime.worker.inFlightRunCount;
|
|
222
|
+
},
|
|
223
|
+
start: () => runtime.worker.start(),
|
|
224
|
+
stop: async () => {
|
|
225
|
+
heapMonitor.stop();
|
|
226
|
+
await runtime.worker.stop();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
return { runtime: { ...runtime, worker }, cors: corsFromConfig, routes, logger };
|
|
277
230
|
}
|
|
278
231
|
|
|
279
232
|
// src/log-meta.ts
|
|
@@ -389,302 +342,65 @@ ${rendered}` : ""}`);
|
|
|
389
342
|
};
|
|
390
343
|
}
|
|
391
344
|
|
|
392
|
-
// src/
|
|
393
|
-
import {
|
|
394
|
-
import {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
import {
|
|
403
|
-
isTerminalRunStatus
|
|
404
|
-
} from "@skein-js/core";
|
|
405
|
-
import { SuperJSON } from "superjson";
|
|
406
|
-
import { z } from "zod";
|
|
407
|
-
var OPS_FILE = ".langgraphjs_ops.json";
|
|
408
|
-
var STORE_FILE = ".langgraphjs_api.store.json";
|
|
409
|
-
var CHECKPOINTER_FILE = ".langgraphjs_api.checkpointer.json";
|
|
410
|
-
var langgraphSuperjson = new SuperJSON();
|
|
411
|
-
langgraphSuperjson.registerCustom(
|
|
412
|
-
{
|
|
413
|
-
isApplicable: (value) => value instanceof Uint8Array,
|
|
414
|
-
serialize: (value) => Buffer.from(value).toString("base64"),
|
|
415
|
-
deserialize: (value) => new Uint8Array(Buffer.from(value, "base64"))
|
|
416
|
-
},
|
|
417
|
-
"Uint8Array"
|
|
418
|
-
);
|
|
419
|
-
var timestamp = z.union([z.date(), z.string()]).optional();
|
|
420
|
-
var jsonObject = z.record(z.unknown());
|
|
421
|
-
var langgraphAssistantSchema = z.object({
|
|
422
|
-
assistant_id: z.string(),
|
|
423
|
-
graph_id: z.string(),
|
|
424
|
-
name: z.string().optional(),
|
|
425
|
-
description: z.string().nullish(),
|
|
426
|
-
config: jsonObject.optional(),
|
|
427
|
-
context: z.unknown().optional(),
|
|
428
|
-
metadata: jsonObject.optional(),
|
|
429
|
-
version: z.number().optional(),
|
|
430
|
-
created_at: timestamp,
|
|
431
|
-
updated_at: timestamp
|
|
432
|
-
}).passthrough();
|
|
433
|
-
var langgraphAssistantVersionSchema = z.object({
|
|
434
|
-
assistant_id: z.string(),
|
|
435
|
-
version: z.number(),
|
|
436
|
-
graph_id: z.string(),
|
|
437
|
-
name: z.string().optional(),
|
|
438
|
-
description: z.string().nullish(),
|
|
439
|
-
config: jsonObject.optional(),
|
|
440
|
-
context: z.unknown().optional(),
|
|
441
|
-
metadata: jsonObject.optional(),
|
|
442
|
-
created_at: timestamp
|
|
443
|
-
}).passthrough();
|
|
444
|
-
var langgraphThreadSchema = z.object({
|
|
445
|
-
thread_id: z.string(),
|
|
446
|
-
status: z.string().optional(),
|
|
447
|
-
metadata: jsonObject.optional(),
|
|
448
|
-
values: jsonObject.optional(),
|
|
449
|
-
interrupts: jsonObject.optional(),
|
|
450
|
-
created_at: timestamp,
|
|
451
|
-
updated_at: timestamp
|
|
452
|
-
}).passthrough();
|
|
453
|
-
var langgraphRunSchema = z.object({
|
|
454
|
-
run_id: z.string(),
|
|
455
|
-
thread_id: z.string(),
|
|
456
|
-
assistant_id: z.string(),
|
|
457
|
-
status: z.string().optional(),
|
|
458
|
-
metadata: jsonObject.optional(),
|
|
459
|
-
multitask_strategy: z.string().nullish(),
|
|
460
|
-
kwargs: jsonObject.optional(),
|
|
461
|
-
created_at: timestamp,
|
|
462
|
-
updated_at: timestamp
|
|
463
|
-
}).passthrough();
|
|
464
|
-
var langgraphOpsSchema = z.object({
|
|
465
|
-
assistants: z.record(langgraphAssistantSchema).optional(),
|
|
466
|
-
assistant_versions: z.array(langgraphAssistantVersionSchema).optional(),
|
|
467
|
-
threads: z.record(langgraphThreadSchema).optional(),
|
|
468
|
-
runs: z.record(langgraphRunSchema).optional()
|
|
469
|
-
}).passthrough();
|
|
470
|
-
var langgraphStoreItemSchema = z.object({
|
|
471
|
-
namespace: z.array(z.string()),
|
|
472
|
-
key: z.string(),
|
|
473
|
-
value: jsonObject,
|
|
474
|
-
createdAt: timestamp,
|
|
475
|
-
updatedAt: timestamp
|
|
476
|
-
}).passthrough();
|
|
477
|
-
var langgraphStoreFileSchema = z.object({ data: z.map(z.string(), z.map(z.string(), langgraphStoreItemSchema)).optional() }).passthrough();
|
|
478
|
-
var langgraphCheckpointerSchema = z.object({ storage: jsonObject, writes: jsonObject }).passthrough();
|
|
479
|
-
async function readSuperjsonFile(filepath) {
|
|
480
|
-
let text;
|
|
345
|
+
// src/heap-headroom.ts
|
|
346
|
+
import { readFileSync } from "fs";
|
|
347
|
+
import { getHeapStatistics as getHeapStatistics2 } from "v8";
|
|
348
|
+
var HEAP_LIMIT_WARN_FRACTION = 0.75;
|
|
349
|
+
var HEAP_LIMIT_SUGGEST_FRACTION = 0.6;
|
|
350
|
+
var MEMORY_LIMIT_FILES = [
|
|
351
|
+
"/sys/fs/cgroup/memory.max",
|
|
352
|
+
"/sys/fs/cgroup/memory/memory.limit_in_bytes"
|
|
353
|
+
];
|
|
354
|
+
var readFileIfPresent = (path) => {
|
|
481
355
|
try {
|
|
482
|
-
|
|
356
|
+
return readFileSync(path, "utf8");
|
|
483
357
|
} catch {
|
|
484
|
-
return
|
|
485
|
-
}
|
|
486
|
-
try {
|
|
487
|
-
return langgraphSuperjson.parse(text) ?? null;
|
|
488
|
-
} catch (error) {
|
|
489
|
-
throw new Error(
|
|
490
|
-
`Could not parse LangGraph state file "${filepath}": ${error instanceof Error ? error.message : String(error)}`
|
|
491
|
-
);
|
|
358
|
+
return void 0;
|
|
492
359
|
}
|
|
493
|
-
}
|
|
494
|
-
function
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
360
|
+
};
|
|
361
|
+
function readContainerMemoryLimit(readFile = readFileIfPresent) {
|
|
362
|
+
for (const path of MEMORY_LIMIT_FILES) {
|
|
363
|
+
const raw = readFile(path)?.trim();
|
|
364
|
+
if (raw === void 0 || raw === "" || raw === "max") continue;
|
|
365
|
+
const bytes = Number(raw);
|
|
366
|
+
if (!Number.isFinite(bytes) || bytes <= 0) continue;
|
|
367
|
+
if (bytes >= Number.MAX_SAFE_INTEGER) continue;
|
|
368
|
+
return bytes;
|
|
499
369
|
}
|
|
500
|
-
return
|
|
501
|
-
}
|
|
502
|
-
function toIso(value, fallback) {
|
|
503
|
-
if (value instanceof Date) return value.toISOString();
|
|
504
|
-
if (typeof value === "string") return value;
|
|
505
|
-
return fallback;
|
|
506
|
-
}
|
|
507
|
-
function toAssistant(row, now) {
|
|
508
|
-
return {
|
|
509
|
-
assistant_id: row.assistant_id,
|
|
510
|
-
graph_id: row.graph_id,
|
|
511
|
-
name: row.name ?? row.graph_id,
|
|
512
|
-
description: row.description ?? void 0,
|
|
513
|
-
config: row.config ?? {},
|
|
514
|
-
context: row.context ?? {},
|
|
515
|
-
metadata: row.metadata ?? {},
|
|
516
|
-
version: row.version ?? 1,
|
|
517
|
-
created_at: toIso(row.created_at, now),
|
|
518
|
-
updated_at: toIso(row.updated_at, now)
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
function toAssistantVersion(row, now) {
|
|
522
|
-
return {
|
|
523
|
-
assistant_id: row.assistant_id,
|
|
524
|
-
version: row.version,
|
|
525
|
-
graph_id: row.graph_id,
|
|
526
|
-
name: row.name ?? row.graph_id,
|
|
527
|
-
description: row.description ?? void 0,
|
|
528
|
-
config: row.config ?? {},
|
|
529
|
-
context: row.context ?? {},
|
|
530
|
-
metadata: row.metadata ?? {},
|
|
531
|
-
created_at: toIso(row.created_at, now)
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
function toThread(row, now) {
|
|
535
|
-
const createdAt = toIso(row.created_at, now);
|
|
536
|
-
const updatedAt = toIso(row.updated_at, createdAt);
|
|
537
|
-
return {
|
|
538
|
-
thread_id: row.thread_id,
|
|
539
|
-
status: row.status ?? "idle",
|
|
540
|
-
metadata: row.metadata ?? {},
|
|
541
|
-
values: row.values ?? {},
|
|
542
|
-
interrupts: row.interrupts ?? {},
|
|
543
|
-
created_at: createdAt,
|
|
544
|
-
updated_at: updatedAt,
|
|
545
|
-
state_updated_at: updatedAt
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
function toRun(row, now) {
|
|
549
|
-
const createdAt = toIso(row.created_at, now);
|
|
550
|
-
const status = row.status ?? "success";
|
|
551
|
-
return {
|
|
552
|
-
run_id: row.run_id,
|
|
553
|
-
thread_id: row.thread_id,
|
|
554
|
-
assistant_id: row.assistant_id,
|
|
555
|
-
status: isTerminalRunStatus(status) ? status : "error",
|
|
556
|
-
metadata: row.metadata ?? {},
|
|
557
|
-
multitask_strategy: row.multitask_strategy ?? null,
|
|
558
|
-
created_at: createdAt,
|
|
559
|
-
updated_at: toIso(row.updated_at, createdAt)
|
|
560
|
-
};
|
|
370
|
+
return void 0;
|
|
561
371
|
}
|
|
562
|
-
function
|
|
563
|
-
|
|
564
|
-
const {
|
|
565
|
-
input,
|
|
566
|
-
command,
|
|
567
|
-
config,
|
|
568
|
-
context,
|
|
569
|
-
stream_mode,
|
|
570
|
-
interrupt_before,
|
|
571
|
-
interrupt_after,
|
|
572
|
-
webhook
|
|
573
|
-
} = kwargs;
|
|
574
|
-
return {
|
|
575
|
-
input,
|
|
576
|
-
command,
|
|
577
|
-
config,
|
|
578
|
-
context,
|
|
579
|
-
stream_mode,
|
|
580
|
-
interrupt_before,
|
|
581
|
-
interrupt_after,
|
|
582
|
-
...typeof webhook === "string" ? { webhook } : {}
|
|
583
|
-
};
|
|
372
|
+
function megabytes2(bytes) {
|
|
373
|
+
return `${Math.round(bytes / 1048576)}MB`;
|
|
584
374
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
readSuperjsonFile(path.join(langgraphApiDir, OPS_FILE)),
|
|
589
|
-
readSuperjsonFile(path.join(langgraphApiDir, STORE_FILE)),
|
|
590
|
-
readSuperjsonFile(path.join(langgraphApiDir, CHECKPOINTER_FILE))
|
|
591
|
-
]);
|
|
592
|
-
if (!opsRaw && !storeRaw && !checkpointerRaw) return null;
|
|
593
|
-
const ops = opsRaw ? validateShape(langgraphOpsSchema, opsRaw, OPS_FILE) : null;
|
|
594
|
-
const storeFile = storeRaw ? validateShape(langgraphStoreFileSchema, storeRaw, STORE_FILE) : null;
|
|
595
|
-
const checkpointerFile = checkpointerRaw ? validateShape(langgraphCheckpointerSchema, checkpointerRaw, CHECKPOINTER_FILE) : null;
|
|
596
|
-
const runEntries = Object.entries(ops?.runs ?? {});
|
|
597
|
-
const items = [];
|
|
598
|
-
if (storeFile?.data) {
|
|
599
|
-
for (const namespaceItems of storeFile.data.values()) {
|
|
600
|
-
for (const stored of namespaceItems.values()) {
|
|
601
|
-
const item = {
|
|
602
|
-
namespace: stored.namespace,
|
|
603
|
-
key: stored.key,
|
|
604
|
-
value: stored.value,
|
|
605
|
-
createdAt: toIso(stored.createdAt, now),
|
|
606
|
-
updatedAt: toIso(stored.updatedAt, now)
|
|
607
|
-
};
|
|
608
|
-
items.push([JSON.stringify([stored.namespace, stored.key]), item]);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
const store = {
|
|
613
|
-
assistants: Object.entries(ops?.assistants ?? {}).map(([id, row]) => [
|
|
614
|
-
id,
|
|
615
|
-
toAssistant(row, now)
|
|
616
|
-
]),
|
|
617
|
-
assistantVersions: (ops?.assistant_versions ?? []).map((row) => [
|
|
618
|
-
JSON.stringify([row.assistant_id, row.version]),
|
|
619
|
-
toAssistantVersion(row, now)
|
|
620
|
-
]),
|
|
621
|
-
threads: Object.entries(ops?.threads ?? {}).map(([id, row]) => [id, toThread(row, now)]),
|
|
622
|
-
runs: runEntries.map(([id, row]) => [id, toRun(row, now)]),
|
|
623
|
-
runKwargs: runEntries.map(([id, row]) => [id, toRunKwargs(row.kwargs)]),
|
|
624
|
-
items
|
|
625
|
-
};
|
|
626
|
-
let checkpoints = { storage: {}, writes: {} };
|
|
627
|
-
if (checkpointerFile) {
|
|
628
|
-
const saver = new MemorySaver3();
|
|
629
|
-
saver.storage = checkpointerFile.storage;
|
|
630
|
-
saver.writes = checkpointerFile.writes;
|
|
631
|
-
checkpoints = snapshotCheckpointer(saver);
|
|
375
|
+
function describeHeapHeadroom(heapLimitBytes, containerLimitBytes) {
|
|
376
|
+
if (containerLimitBytes === void 0 || heapLimitBytes <= containerLimitBytes * HEAP_LIMIT_WARN_FRACTION) {
|
|
377
|
+
return { heapLimitBytes, containerLimitBytes, warning: void 0 };
|
|
632
378
|
}
|
|
633
|
-
|
|
634
|
-
}
|
|
635
|
-
function describeSnapshot(snapshot) {
|
|
379
|
+
const suggestedMb = Math.floor(containerLimitBytes * HEAP_LIMIT_SUGGEST_FRACTION / 1048576);
|
|
636
380
|
return {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
items: snapshot.store.items.length,
|
|
641
|
-
checkpointedThreads: Object.keys(snapshot.checkpoints.storage).length
|
|
381
|
+
heapLimitBytes,
|
|
382
|
+
containerLimitBytes,
|
|
383
|
+
warning: `V8's heap limit (${megabytes2(heapLimitBytes)}) is close to or above this container's memory limit (${megabytes2(containerLimitBytes)}). Node's automatic sizing has a floor of about 259MB, so below roughly 345Mi it stops adapting \u2014 V8 may not run a full GC before the kernel OOM-kills the process, which looks like an unexplained restart rather than a memory error. Lower it explicitly with NODE_OPTIONS="--enable-source-maps --max-old-space-size=${suggestedMb}", or give the container more memory. Keep --enable-source-maps: NODE_OPTIONS replaces the image's value rather than adding to it, so setting it without that flag silently loses TypeScript stack traces.`
|
|
642
384
|
};
|
|
643
385
|
}
|
|
644
|
-
function
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
async function copyCheckpoints(snapshot, target) {
|
|
648
|
-
const source = new MemorySaver3();
|
|
649
|
-
hydrateCheckpointer(source, snapshot);
|
|
650
|
-
const tuples = [];
|
|
651
|
-
for await (const tuple of source.list({})) tuples.push(tuple);
|
|
652
|
-
tuples.reverse();
|
|
653
|
-
for (const tuple of tuples) {
|
|
654
|
-
const configurable = tuple.config.configurable ?? {};
|
|
655
|
-
const putConfig = {
|
|
656
|
-
configurable: {
|
|
657
|
-
thread_id: configurable.thread_id,
|
|
658
|
-
checkpoint_ns: configurable.checkpoint_ns ?? "",
|
|
659
|
-
// `put` reads `checkpoint_id` as the PARENT pointer; the child's own id is `checkpoint.id`.
|
|
660
|
-
checkpoint_id: tuple.parentConfig?.configurable?.checkpoint_id
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
const stored = await target.put(
|
|
664
|
-
putConfig,
|
|
665
|
-
tuple.checkpoint,
|
|
666
|
-
tuple.metadata ?? {},
|
|
667
|
-
tuple.checkpoint.channel_versions ?? {}
|
|
668
|
-
);
|
|
669
|
-
const writesByTask = /* @__PURE__ */ new Map();
|
|
670
|
-
for (const [taskId, channel, value] of tuple.pendingWrites ?? []) {
|
|
671
|
-
const writes = writesByTask.get(taskId) ?? [];
|
|
672
|
-
writes.push([channel, value]);
|
|
673
|
-
writesByTask.set(taskId, writes);
|
|
674
|
-
}
|
|
675
|
-
for (const [taskId, writes] of writesByTask) {
|
|
676
|
-
await target.putWrites(stored, writes, taskId);
|
|
677
|
-
}
|
|
678
|
-
}
|
|
386
|
+
function checkHeapHeadroom(options = {}) {
|
|
387
|
+
const heapLimit = (options.heapStatistics ?? getHeapStatistics2)().heap_size_limit;
|
|
388
|
+
return describeHeapHeadroom(heapLimit, readContainerMemoryLimit(options.readFile));
|
|
679
389
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
390
|
+
|
|
391
|
+
// src/index.ts
|
|
392
|
+
import { DEFAULT_RUN_CONCURRENCY as DEFAULT_RUN_CONCURRENCY2 } from "@skein-js/agent-protocol";
|
|
393
|
+
import { DEFAULT_SHUTDOWN_GRACE_MS as DEFAULT_SHUTDOWN_GRACE_MS2 } from "@skein-js/agent-protocol";
|
|
394
|
+
|
|
395
|
+
// src/route-matcher-cache.ts
|
|
396
|
+
import { createRouteMatcher } from "@skein-js/agent-protocol";
|
|
397
|
+
var matchers = /* @__PURE__ */ new WeakMap();
|
|
398
|
+
function routeMatcherFor(routes) {
|
|
399
|
+
const existing = matchers.get(routes);
|
|
400
|
+
if (existing) return existing;
|
|
401
|
+
const matcher = createRouteMatcher(routes);
|
|
402
|
+
matchers.set(routes, matcher);
|
|
403
|
+
return matcher;
|
|
688
404
|
}
|
|
689
405
|
|
|
690
406
|
// src/cors-runtime.ts
|
|
@@ -755,12 +471,15 @@ function sendNodePreflight(reqHeaders, res, cors) {
|
|
|
755
471
|
}
|
|
756
472
|
|
|
757
473
|
// src/node-transport.ts
|
|
758
|
-
import {
|
|
474
|
+
import {
|
|
475
|
+
SSE_HEADERS,
|
|
476
|
+
writeWithBackpressure
|
|
477
|
+
} from "@skein-js/agent-protocol";
|
|
759
478
|
import { isSkeinHttpError, serializeWireJson } from "@skein-js/core";
|
|
760
479
|
var ignoreStreamError = () => {
|
|
761
480
|
};
|
|
762
|
-
async function pipeServerSentEvents(status, events, res) {
|
|
763
|
-
res.writeHead(status, SSE_HEADERS);
|
|
481
|
+
async function pipeServerSentEvents(status, events, res, headers = {}) {
|
|
482
|
+
res.writeHead(status, { ...SSE_HEADERS, ...headers });
|
|
764
483
|
res.flushHeaders();
|
|
765
484
|
const iterator = events[Symbol.asyncIterator]();
|
|
766
485
|
let clientDisconnected = false;
|
|
@@ -774,7 +493,8 @@ async function pipeServerSentEvents(status, events, res) {
|
|
|
774
493
|
for (; ; ) {
|
|
775
494
|
const next = await iterator.next();
|
|
776
495
|
if (next.done || clientDisconnected) break;
|
|
777
|
-
res
|
|
496
|
+
const drained = writeWithBackpressure(res, next.value);
|
|
497
|
+
if (drained) await drained;
|
|
778
498
|
}
|
|
779
499
|
} finally {
|
|
780
500
|
res.removeListener("close", releaseOnClientClose);
|
|
@@ -784,14 +504,17 @@ async function pipeServerSentEvents(status, events, res) {
|
|
|
784
504
|
async function sendNodeResponse(response, res) {
|
|
785
505
|
switch (response.kind) {
|
|
786
506
|
case "json":
|
|
787
|
-
res.writeHead(response.status, {
|
|
507
|
+
res.writeHead(response.status, {
|
|
508
|
+
"content-type": "application/json",
|
|
509
|
+
...response.headers
|
|
510
|
+
});
|
|
788
511
|
res.end(serializeWireJson(response.body));
|
|
789
512
|
return;
|
|
790
513
|
case "empty":
|
|
791
|
-
res.writeHead(response.status).end();
|
|
514
|
+
res.writeHead(response.status, response.headers).end();
|
|
792
515
|
return;
|
|
793
516
|
case "sse":
|
|
794
|
-
await pipeServerSentEvents(response.status, response.events, res);
|
|
517
|
+
await pipeServerSentEvents(response.status, response.events, res, response.headers);
|
|
795
518
|
return;
|
|
796
519
|
}
|
|
797
520
|
}
|
|
@@ -831,35 +554,139 @@ function stripBasePath(pathname, basePath) {
|
|
|
831
554
|
if (pathname.startsWith(`${prefix}/`)) return pathname.slice(prefix.length);
|
|
832
555
|
return null;
|
|
833
556
|
}
|
|
557
|
+
|
|
558
|
+
// src/runtime-capabilities.ts
|
|
559
|
+
function detectRuntimeCapabilities(scope = globalThis) {
|
|
560
|
+
const monotonic = () => scope.performance?.now() ?? Date.now();
|
|
561
|
+
const commonClock = { nowEpochMs: Date.now, nowMonotonicMs: monotonic };
|
|
562
|
+
if (scope.Bun) {
|
|
563
|
+
const bun = scope.Bun;
|
|
564
|
+
const process3 = scope.process;
|
|
565
|
+
if (!process3) throw new Error("Bun runtime does not expose process lifecycle compatibility.");
|
|
566
|
+
return {
|
|
567
|
+
name: "bun",
|
|
568
|
+
version: bun.version,
|
|
569
|
+
env: {
|
|
570
|
+
get: (name) => bun.env[name],
|
|
571
|
+
set: (name, value) => {
|
|
572
|
+
bun.env[name] = value;
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
clock: commonClock,
|
|
576
|
+
memory: {
|
|
577
|
+
read: () => {
|
|
578
|
+
const native = bun.memoryUsage?.();
|
|
579
|
+
const fallback = process3.memoryUsage();
|
|
580
|
+
return {
|
|
581
|
+
rssBytes: native?.rss ?? fallback.rss,
|
|
582
|
+
heapUsedBytes: native?.heapUsed ?? fallback.heapUsed,
|
|
583
|
+
nativeHeapBytes: native?.current
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
signals: {
|
|
588
|
+
on: (signal, listener) => {
|
|
589
|
+
process3.on(signal, listener);
|
|
590
|
+
return { dispose: () => process3.off(signal, listener) };
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
exit: (code) => process3.exit(code)
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
if (scope.Deno) {
|
|
597
|
+
const deno = scope.Deno;
|
|
598
|
+
return {
|
|
599
|
+
name: "deno",
|
|
600
|
+
version: deno.version.deno,
|
|
601
|
+
env: deno.env,
|
|
602
|
+
clock: commonClock,
|
|
603
|
+
memory: {
|
|
604
|
+
read: () => {
|
|
605
|
+
const memory = deno.memoryUsage();
|
|
606
|
+
return { rssBytes: memory.rss, heapUsedBytes: memory.heapUsed };
|
|
607
|
+
}
|
|
608
|
+
},
|
|
609
|
+
signals: {
|
|
610
|
+
on: (signal, listener) => {
|
|
611
|
+
deno.addSignalListener(signal, listener);
|
|
612
|
+
return { dispose: () => deno.removeSignalListener(signal, listener) };
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
exit: (code) => deno.exit(code)
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
const process2 = scope.process;
|
|
619
|
+
if (!process2)
|
|
620
|
+
throw new Error("Unsupported JavaScript runtime: process, Bun, and Deno are absent.");
|
|
621
|
+
return {
|
|
622
|
+
name: "node",
|
|
623
|
+
version: process2.version.replace(/^v/, ""),
|
|
624
|
+
env: {
|
|
625
|
+
get: (name) => process2.env[name],
|
|
626
|
+
set: (name, value) => {
|
|
627
|
+
process2.env[name] = value;
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
clock: commonClock,
|
|
631
|
+
memory: {
|
|
632
|
+
read: () => {
|
|
633
|
+
const memory = process2.memoryUsage();
|
|
634
|
+
return { rssBytes: memory.rss, heapUsedBytes: memory.heapUsed };
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
signals: {
|
|
638
|
+
on: (signal, listener) => {
|
|
639
|
+
process2.on(signal, listener);
|
|
640
|
+
return { dispose: () => process2.off(signal, listener) };
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
exit: (code) => process2.exit(code)
|
|
644
|
+
};
|
|
645
|
+
}
|
|
834
646
|
export {
|
|
647
|
+
DEFAULT_HEAP_SAMPLE_MS,
|
|
648
|
+
DEFAULT_HEAP_WARN_PERCENT,
|
|
835
649
|
DEFAULT_RUN_CONCURRENCY2 as DEFAULT_RUN_CONCURRENCY,
|
|
836
650
|
DEFAULT_SHUTDOWN_GRACE_MS2 as DEFAULT_SHUTDOWN_GRACE_MS,
|
|
651
|
+
HEAP_REARM_MARGIN_PERCENT,
|
|
652
|
+
HEAP_REARM_PERCENT,
|
|
837
653
|
allowedOrigin,
|
|
838
654
|
applyNodeCors,
|
|
655
|
+
checkHeapHeadroom,
|
|
839
656
|
corsFromHttpConfig,
|
|
840
657
|
corsPreflightHeaders,
|
|
841
658
|
corsResponseHeaders,
|
|
842
659
|
createConsoleLogger,
|
|
843
660
|
createInMemoryDeps,
|
|
844
661
|
describeError,
|
|
845
|
-
|
|
662
|
+
describeHeapHeadroom,
|
|
663
|
+
describePoolPressure,
|
|
664
|
+
detectRuntimeCapabilities,
|
|
665
|
+
disabledRoutesFromHttpConfig,
|
|
846
666
|
embedInMemoryGraphs,
|
|
847
667
|
formatLogMeta,
|
|
848
668
|
graphMapToResolver,
|
|
849
669
|
joinList,
|
|
850
670
|
loadInMemoryRuntime,
|
|
851
671
|
loadReloadableInMemoryRuntime,
|
|
852
|
-
loadSnapshotIntoStore,
|
|
853
672
|
normalizeEmbeddableGraphs,
|
|
854
|
-
|
|
673
|
+
readContainerMemoryLimit,
|
|
674
|
+
resolveCronTickMs,
|
|
675
|
+
resolveHeapPressureOptions,
|
|
676
|
+
resolveMaxPageSize,
|
|
677
|
+
resolveMemoryBusLimits,
|
|
855
678
|
resolveProtocolRuntime,
|
|
856
679
|
resolveRunConcurrency,
|
|
680
|
+
resolveRunTimeoutMs,
|
|
857
681
|
resolveRuntimeDeps,
|
|
858
682
|
resolveShutdownGraceMs,
|
|
683
|
+
routeMatcherFor,
|
|
684
|
+
routesFromHttpConfig,
|
|
859
685
|
runFailureIdentity,
|
|
860
686
|
sendNodeError,
|
|
861
687
|
sendNodePreflight,
|
|
862
688
|
sendNodeResponse,
|
|
689
|
+
startHeapPressureMonitor,
|
|
863
690
|
stripBasePath,
|
|
864
691
|
toCorsOptions
|
|
865
692
|
};
|