@agent-team-foundation/first-tree-hub 0.9.3 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{bootstrap-CWcBzk6C.mjs → bootstrap-DWifXj9b.mjs} +5 -5
- package/dist/cli/index.mjs +193 -171
- package/dist/{core-Y7M3d2aZ.mjs → core-USyOOh7y.mjs} +641 -2969
- package/dist/index.mjs +4 -4
- package/dist/{logger-core-2yeIU1fc-B-__AsQO.mjs → logger-core-BTmvdflj-DhdipBkV.mjs} +40 -5
- package/dist/{observability-CJzDFY_G-CmvgUuzc.mjs → observability-DV_fQKqV-CuLWzBxQ.mjs} +8 -3
- package/dist/{observability-Xi-sEZI7.mjs → observability-hDEdrmMS.mjs} +2 -2
- package/dist/web/assets/index-CzlAfdgm.js +361 -0
- package/dist/web/assets/index-DEwlT6PE.css +1 -0
- package/dist/web/fonts/inter-latin-ext.woff2 +0 -0
- package/dist/web/fonts/inter-latin.woff2 +0 -0
- package/dist/web/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
- package/dist/web/fonts/jetbrains-mono-latin.woff2 +0 -0
- package/dist/web/index.html +4 -2
- package/package.json +1 -1
- package/dist/web/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- package/dist/web/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- package/dist/web/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- package/dist/web/assets/geist-mono-cyrillic-wght-normal-BZdD_g9V.woff2 +0 -0
- package/dist/web/assets/geist-mono-latin-ext-wght-normal-b6lpi8_2.woff2 +0 -0
- package/dist/web/assets/geist-mono-latin-wght-normal-Cjtb1TV-.woff2 +0 -0
- package/dist/web/assets/index-C3GFm5oL.js +0 -361
- package/dist/web/assets/index-DEbM78Bl.css +0 -1
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { m as __toESM } from "./esm-CYu4tXXn.mjs";
|
|
2
|
+
import { _ as withSpan, a as endWsConnectionSpan, b as require_pino, c as messageAttrs, d as rootLogger$1, g as startWsConnectionSpan, i as currentTraceId, n as applyLoggerConfig, o as getFastifyOtelPlugin, p as setWsConnectionAttrs, r as createLogger$1, t as adapterAttrs, u as observabilityPlugin, v as withWsMessageSpan, y as FIRST_TREE_HUB_ATTR } from "./observability-DV_fQKqV-CuLWzBxQ.mjs";
|
|
3
|
+
import { s as formatPrettyEntry$1, t as LOG_LEVELS$1, u as parseLogLevel$1 } from "./logger-core-BTmvdflj-DhdipBkV.mjs";
|
|
4
|
+
import { C as serverConfigSchema, S as resolveConfigReadonly, _ as loadAgents, d as DEFAULT_HOME_DIR$1, f as agentConfigSchema, g as initConfig, i as loadCredentials, l as DEFAULT_CONFIG_DIR, m as collectMissingPrompts, n as ensureFreshAccessToken, o as resolveServerUrl, p as clientConfigSchema, s as saveAgentConfig, u as DEFAULT_DATA_DIR$1, v as migrateLegacyHome, w as setConfigValue } from "./bootstrap-DWifXj9b.mjs";
|
|
4
5
|
import { $ as updateAdapterConfigSchema, A as createMemberSchema, B as notificationQuerySchema, C as agentTypeSchema$1, D as createAdapterMappingSchema, E as createAdapterConfigSchema, F as inboxPollQuerySchema, G as sendMessageSchema, H as refreshTokenSchema, I as isRedactedEnvValue, J as sessionEventMessageSchema, K as sendToAgentSchema, L as linkTaskChatSchema, M as createTaskSchema, N as delegateFeishuUserSchema, O as createAgentSchema, P as dryRunAgentRuntimeConfigSchema, Q as taskListQuerySchema, R as loginSchema, S as agentRuntimeConfigPayloadSchema$1, T as connectTokenExchangeSchema, U as runtimeStateMessageSchema, V as paginationQuerySchema, W as selfServiceFeishuBotSchema, X as sessionReconcileRequestSchema, Y as sessionEventSchema$1, Z as sessionStateMessageSchema, _ as addParticipantSchema, a as AGENT_SELECTOR_HEADER$1, at as updateSystemConfigSchema, b as agentBindRequestSchema, c as AGENT_TYPES, d as SYSTEM_CONFIG_DEFAULTS, et as updateAgentRuntimeConfigSchema, f as TASK_CREATOR_TYPES, g as WS_AUTH_FRAME_TIMEOUT_MS, h as TASK_TERMINAL_STATUSES, i as AGENT_BIND_REJECT_REASONS, it as updateOrganizationSchema, j as createOrganizationSchema, k as createChatSchema, l as AGENT_VISIBILITY, m as TASK_STATUSES, nt as updateChatSchema, o as AGENT_SOURCES, ot as updateTaskStatusSchema, p as TASK_HEALTH_SIGNALS, q as sessionCompletionMessageSchema, rt as updateMemberSchema, s as AGENT_STATUSES, st as wsAuthFrameSchema, tt as updateAgentSchema, u as DEFAULT_AGENT_RUNTIME_CONFIG_PAYLOAD, v as adminCreateTaskSchema, w as clientRegisterSchema, x as agentPinnedMessageSchema$1, y as adminUpdateTaskSchema, z as messageSourceSchema$1 } from "./feishu-GlaczcVf.mjs";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
|
-
import { copyFileSync, createReadStream, createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, watch, writeFileSync } from "node:fs";
|
|
7
|
-
import { dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
8
7
|
import { ZodError, z } from "zod";
|
|
8
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
9
9
|
import { Writable } from "node:stream";
|
|
10
|
-
import { stringify } from "yaml";
|
|
11
|
-
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
12
10
|
import { homedir, hostname, platform, userInfo } from "node:os";
|
|
13
11
|
import { EventEmitter } from "node:events";
|
|
12
|
+
import { closeSync, copyFileSync, createReadStream, existsSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, unwatchFile, watch, watchFile, writeFileSync, writeSync } from "node:fs";
|
|
13
|
+
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
14
14
|
import WebSocket from "ws";
|
|
15
15
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
16
16
|
import { execFileSync, execSync, spawn, spawnSync } from "node:child_process";
|
|
17
|
+
import { stringify } from "yaml";
|
|
17
18
|
import * as semver from "semver";
|
|
18
19
|
import bcrypt from "bcrypt";
|
|
19
20
|
import { and, asc, count, desc, eq, gt, inArray, isNotNull, isNull, lt, ne, or, sql } from "drizzle-orm";
|
|
@@ -30,7 +31,8 @@ import Fastify from "fastify";
|
|
|
30
31
|
import { bigserial, boolean, index, integer, jsonb, pgTable, primaryKey, serial, text, timestamp, unique, uniqueIndex } from "drizzle-orm/pg-core";
|
|
31
32
|
import { SignJWT, jwtVerify } from "jose";
|
|
32
33
|
import { Client, EventDispatcher, LoggerLevel, WSClient } from "@larksuiteoapi/node-sdk";
|
|
33
|
-
|
|
34
|
+
import { createInterface } from "node:readline";
|
|
35
|
+
//#region ../client/dist/observability-B4kO005X.mjs
|
|
34
36
|
var import_pino = /* @__PURE__ */ __toESM(require_pino(), 1);
|
|
35
37
|
/**
|
|
36
38
|
* Logger core — format / level primitives shared between server and client.
|
|
@@ -97,6 +99,39 @@ const SKIP_KEYS = new Set([
|
|
|
97
99
|
"hostname",
|
|
98
100
|
"v"
|
|
99
101
|
]);
|
|
102
|
+
/**
|
|
103
|
+
* Pino `redact.paths` entries applied to every root logger in Hub. Keeps the
|
|
104
|
+
* list short on purpose — pino's redact walks each path on every log call, so
|
|
105
|
+
* we target obvious sensitive field names plus a narrow set of nested forms
|
|
106
|
+
* (`*.foo` matches a single nesting level in pino v9).
|
|
107
|
+
*
|
|
108
|
+
* Values matching these paths are replaced with the censor string `[REDACTED]`.
|
|
109
|
+
*/
|
|
110
|
+
const LOG_REDACT_PATHS = [
|
|
111
|
+
"password",
|
|
112
|
+
"*.password",
|
|
113
|
+
"token",
|
|
114
|
+
"*.token",
|
|
115
|
+
"accessToken",
|
|
116
|
+
"*.accessToken",
|
|
117
|
+
"refreshToken",
|
|
118
|
+
"*.refreshToken",
|
|
119
|
+
"jwt",
|
|
120
|
+
"*.jwt",
|
|
121
|
+
"secret",
|
|
122
|
+
"*.secret",
|
|
123
|
+
"apiKey",
|
|
124
|
+
"*.apiKey",
|
|
125
|
+
"api_key",
|
|
126
|
+
"*.api_key",
|
|
127
|
+
"credentials",
|
|
128
|
+
"*.credentials",
|
|
129
|
+
"authorization",
|
|
130
|
+
"*.authorization",
|
|
131
|
+
"*.headers.cookie",
|
|
132
|
+
"*.headers.authorization"
|
|
133
|
+
];
|
|
134
|
+
const LOG_REDACT_CENSOR = "[REDACTED]";
|
|
100
135
|
function formatPrettyEntry(json) {
|
|
101
136
|
const obj = JSON.parse(json);
|
|
102
137
|
const level = obj.level;
|
|
@@ -123,42 +158,146 @@ function formatLocalTime() {
|
|
|
123
158
|
return `${d.toLocaleDateString("sv-SE")} ${d.toLocaleTimeString("en-GB", { hour12: false })}`;
|
|
124
159
|
}
|
|
125
160
|
function createLoggerOutputStream(options) {
|
|
161
|
+
const getDest = options.getDestination ?? (() => process.stderr);
|
|
126
162
|
return new Writable({ write(chunk, _, callback) {
|
|
127
163
|
const text = chunk.toString();
|
|
164
|
+
const dest = getDest();
|
|
128
165
|
try {
|
|
129
|
-
if (options.getFormat() === "pretty")
|
|
130
|
-
else
|
|
166
|
+
if (options.getFormat() === "pretty") dest.write(formatPrettyEntry(text));
|
|
167
|
+
else dest.write(text);
|
|
131
168
|
if (options.onJsonEntry) try {
|
|
132
169
|
const obj = JSON.parse(text);
|
|
133
170
|
options.onJsonEntry(obj);
|
|
134
171
|
} catch {}
|
|
135
172
|
} catch {
|
|
136
|
-
|
|
173
|
+
dest.write(text);
|
|
137
174
|
}
|
|
138
175
|
callback();
|
|
139
176
|
} });
|
|
140
177
|
}
|
|
178
|
+
var RotatingFileStream = class extends Writable {
|
|
179
|
+
size;
|
|
180
|
+
fd;
|
|
181
|
+
path;
|
|
182
|
+
maxBytes;
|
|
183
|
+
maxFiles;
|
|
184
|
+
constructor(options) {
|
|
185
|
+
super();
|
|
186
|
+
this.path = options.path;
|
|
187
|
+
this.maxBytes = options.maxBytes;
|
|
188
|
+
this.maxFiles = Math.max(1, options.maxFiles);
|
|
189
|
+
mkdirSync(dirname(this.path), {
|
|
190
|
+
recursive: true,
|
|
191
|
+
mode: 448
|
|
192
|
+
});
|
|
193
|
+
try {
|
|
194
|
+
this.size = statSync(this.path).size;
|
|
195
|
+
} catch {
|
|
196
|
+
this.size = 0;
|
|
197
|
+
}
|
|
198
|
+
this.fd = openSync(this.path, "a", 384);
|
|
199
|
+
}
|
|
200
|
+
_write(chunk, _enc, callback) {
|
|
201
|
+
try {
|
|
202
|
+
const buf = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
203
|
+
writeSync(this.fd, buf);
|
|
204
|
+
this.size += buf.length;
|
|
205
|
+
if (this.size >= this.maxBytes) this.rotate();
|
|
206
|
+
callback();
|
|
207
|
+
} catch (err) {
|
|
208
|
+
callback(err instanceof Error ? err : new Error(String(err)));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
_final(callback) {
|
|
212
|
+
try {
|
|
213
|
+
closeSync(this.fd);
|
|
214
|
+
callback();
|
|
215
|
+
} catch (err) {
|
|
216
|
+
callback(err instanceof Error ? err : new Error(String(err)));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
rotate() {
|
|
220
|
+
closeSync(this.fd);
|
|
221
|
+
for (let i = this.maxFiles - 1; i >= 1; i--) renameIfExists(`${this.path}.${i}`, `${this.path}.${i + 1}`);
|
|
222
|
+
unlinkIfExists(`${this.path}.1`);
|
|
223
|
+
renameSync(this.path, `${this.path}.1`);
|
|
224
|
+
this.fd = openSync(this.path, "a", 384);
|
|
225
|
+
this.size = 0;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
function isNotFound(err) {
|
|
229
|
+
return err instanceof Error && "code" in err && err.code === "ENOENT";
|
|
230
|
+
}
|
|
231
|
+
function renameIfExists(from, to) {
|
|
232
|
+
try {
|
|
233
|
+
unlinkIfExists(to);
|
|
234
|
+
renameSync(from, to);
|
|
235
|
+
} catch (err) {
|
|
236
|
+
if (!isNotFound(err)) throw err;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function unlinkIfExists(path) {
|
|
240
|
+
try {
|
|
241
|
+
unlinkSync(path);
|
|
242
|
+
} catch (err) {
|
|
243
|
+
if (!isNotFound(err)) throw err;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Rotation defaults for the background service log file. */
|
|
247
|
+
const SERVICE_LOG_MAX_BYTES = 10 * 1024 * 1024;
|
|
248
|
+
const SERVICE_LOG_MAX_FILES = 7;
|
|
141
249
|
/**
|
|
142
250
|
* Client-side logger. Same pretty / NDJSON formats as the server logger, but
|
|
143
251
|
* intentionally lightweight — the client is deployed to agent user machines,
|
|
144
252
|
* so we skip tracing, context propagation, and error sinks.
|
|
145
253
|
*/
|
|
146
254
|
const initialLevel = parseLogLevel(process.env.FIRST_TREE_HUB_LOG_LEVEL);
|
|
255
|
+
const initialPinoLevel = process.env.NODE_ENV === "test" && !process.env.FIRST_TREE_HUB_LOG_LEVEL ? "silent" : initialLevel.level;
|
|
147
256
|
let _format = process.env.NODE_ENV === "production" ? "json" : "pretty";
|
|
148
|
-
let
|
|
257
|
+
let _destination = process.stderr;
|
|
258
|
+
let _levelExplicit = false;
|
|
149
259
|
function applyClientLoggerConfig(options = {}) {
|
|
150
|
-
if (options.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
260
|
+
if (options.explicit === false) _levelExplicit = false;
|
|
261
|
+
if (options.level !== void 0 && (options.explicit === true || !_levelExplicit)) rootLogger.level = options.level;
|
|
262
|
+
if (options.explicit === true) _levelExplicit = true;
|
|
154
263
|
if (options.format) _format = options.format;
|
|
264
|
+
if (options.destination) _destination = options.destination;
|
|
155
265
|
}
|
|
156
|
-
const outputStream = createLoggerOutputStream({
|
|
266
|
+
const outputStream = createLoggerOutputStream({
|
|
267
|
+
getFormat: () => _format,
|
|
268
|
+
getDestination: () => _destination
|
|
269
|
+
});
|
|
157
270
|
const rootLogger = (0, import_pino.default)({
|
|
158
|
-
level:
|
|
159
|
-
timestamp: () => `,"time":"${formatLocalTime()}"
|
|
271
|
+
level: initialPinoLevel,
|
|
272
|
+
timestamp: () => `,"time":"${formatLocalTime()}"`,
|
|
273
|
+
redact: {
|
|
274
|
+
paths: [...LOG_REDACT_PATHS],
|
|
275
|
+
censor: LOG_REDACT_CENSOR
|
|
276
|
+
}
|
|
160
277
|
}, outputStream);
|
|
161
278
|
if (initialLevel.fellBack) rootLogger.warn({ envValue: process.env.FIRST_TREE_HUB_LOG_LEVEL }, "invalid FIRST_TREE_HUB_LOG_LEVEL; falling back to info");
|
|
279
|
+
function createLogger(module) {
|
|
280
|
+
return rootLogger.child({ module });
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Switch the client logger over to the background-service file sink.
|
|
284
|
+
*
|
|
285
|
+
* The launchd / systemd unit files already set `StandardOutPath` /
|
|
286
|
+
* `StandardError` as a fallback for crash-time stderr; this routes normal
|
|
287
|
+
* operational logs into a size-rotated NDJSON file at
|
|
288
|
+
* `<logDir>/client.log` so it doesn't grow unbounded. Must be called once
|
|
289
|
+
* at `client start` when running under `FIRST_TREE_HUB_SERVICE_MODE=1`.
|
|
290
|
+
*/
|
|
291
|
+
function configureClientLoggerForService(logDir) {
|
|
292
|
+
applyClientLoggerConfig({
|
|
293
|
+
format: "json",
|
|
294
|
+
destination: new RotatingFileStream({
|
|
295
|
+
path: join(logDir, "client.log"),
|
|
296
|
+
maxBytes: SERVICE_LOG_MAX_BYTES,
|
|
297
|
+
maxFiles: SERVICE_LOG_MAX_FILES
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
}
|
|
162
301
|
//#endregion
|
|
163
302
|
//#region ../client/dist/index.mjs
|
|
164
303
|
const adapterPlatformSchema = z.enum([
|
|
@@ -1148,6 +1287,8 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1148
1287
|
registered = false;
|
|
1149
1288
|
/** Count of `server:welcome` frames received; drives `isReconnect` flag. */
|
|
1150
1289
|
welcomeFramesReceived = 0;
|
|
1290
|
+
wsLogger;
|
|
1291
|
+
authLogger;
|
|
1151
1292
|
boundAgents = /* @__PURE__ */ new Map();
|
|
1152
1293
|
/** Agents scheduled to rebind automatically on every reconnect. */
|
|
1153
1294
|
desiredBindings = /* @__PURE__ */ new Map();
|
|
@@ -1158,6 +1299,8 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1158
1299
|
this.serverUrl = config.serverUrl.replace(/\/+$/, "");
|
|
1159
1300
|
this.sdkVersion = config.sdkVersion;
|
|
1160
1301
|
this.getAccessToken = config.getAccessToken;
|
|
1302
|
+
this.wsLogger = createLogger("ws").child({ clientId: this.clientId });
|
|
1303
|
+
this.authLogger = createLogger("auth").child({ clientId: this.clientId });
|
|
1161
1304
|
this.on("error", () => {});
|
|
1162
1305
|
}
|
|
1163
1306
|
get isConnected() {
|
|
@@ -1270,7 +1413,9 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1270
1413
|
}
|
|
1271
1414
|
openWebSocket() {
|
|
1272
1415
|
return new Promise((resolve, reject) => {
|
|
1273
|
-
const
|
|
1416
|
+
const wsUrl = `${this.serverUrl.replace(/^http/, "ws")}/api/v1/agent/ws/client`;
|
|
1417
|
+
this.wsLogger.info({ url: wsUrl }, "connecting");
|
|
1418
|
+
const ws = new WebSocket(wsUrl);
|
|
1274
1419
|
let settled = false;
|
|
1275
1420
|
const settle = (fn, value) => {
|
|
1276
1421
|
if (settled) return;
|
|
@@ -1290,6 +1435,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1290
1435
|
ws.on("open", async () => {
|
|
1291
1436
|
this.ws = ws;
|
|
1292
1437
|
this.reconnectAttempt = 0;
|
|
1438
|
+
this.wsLogger.debug("socket opened, sending auth");
|
|
1293
1439
|
try {
|
|
1294
1440
|
const token = await this.getAccessToken();
|
|
1295
1441
|
ws.send(JSON.stringify({
|
|
@@ -1298,6 +1444,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1298
1444
|
}));
|
|
1299
1445
|
this.scheduleProactiveAuthRefresh(token);
|
|
1300
1446
|
} catch (err) {
|
|
1447
|
+
this.authLogger.error({ err }, "failed to obtain access token");
|
|
1301
1448
|
settle(reject, err instanceof Error ? err : new Error(String(err)));
|
|
1302
1449
|
ws.close();
|
|
1303
1450
|
}
|
|
@@ -1315,9 +1462,14 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1315
1462
|
this.registered = false;
|
|
1316
1463
|
this.rejectAllPendingBinds("WebSocket closed");
|
|
1317
1464
|
if (!settled) {
|
|
1465
|
+
this.wsLogger.warn({ code }, "closed before ready");
|
|
1318
1466
|
settle(reject, /* @__PURE__ */ new Error(`WebSocket closed before ready (code ${code})`));
|
|
1319
1467
|
return;
|
|
1320
1468
|
}
|
|
1469
|
+
this.wsLogger.warn({
|
|
1470
|
+
code,
|
|
1471
|
+
wasRegistered
|
|
1472
|
+
}, "disconnected");
|
|
1321
1473
|
if (!this.closing) {
|
|
1322
1474
|
this.emit("disconnected");
|
|
1323
1475
|
if (wasRegistered) this.scheduleReconnect();
|
|
@@ -1331,6 +1483,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1331
1483
|
handleMessage(msg, connectResolve) {
|
|
1332
1484
|
const type = msg.type;
|
|
1333
1485
|
if (type === "auth:ok") {
|
|
1486
|
+
this.authLogger.info("auth accepted, registering client");
|
|
1334
1487
|
this.ws?.send(JSON.stringify({
|
|
1335
1488
|
type: "client:register",
|
|
1336
1489
|
clientId: this.clientId,
|
|
@@ -1343,7 +1496,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1343
1496
|
if (type === "server:welcome") {
|
|
1344
1497
|
const parsed = serverWelcomeFrameSchema.safeParse(msg);
|
|
1345
1498
|
if (!parsed.success) {
|
|
1346
|
-
|
|
1499
|
+
this.wsLogger.warn({ issues: parsed.error.issues.map((i) => i.message) }, "ignoring malformed server:welcome frame");
|
|
1347
1500
|
return;
|
|
1348
1501
|
}
|
|
1349
1502
|
const isReconnect = this.welcomeFramesReceived > 0;
|
|
@@ -1355,12 +1508,16 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1355
1508
|
return;
|
|
1356
1509
|
}
|
|
1357
1510
|
if (type === "auth:rejected" || type === "auth:expired") {
|
|
1358
|
-
if (type === "auth:expired")
|
|
1511
|
+
if (type === "auth:expired") {
|
|
1512
|
+
this.authLogger.info("token expired, reconnecting with fresh token");
|
|
1513
|
+
this.emit("auth:expired");
|
|
1514
|
+
} else this.authLogger.warn("auth rejected by server");
|
|
1359
1515
|
this.ws?.close(4401, type);
|
|
1360
1516
|
return;
|
|
1361
1517
|
}
|
|
1362
1518
|
if (type === "client:register:rejected") {
|
|
1363
1519
|
const err = /* @__PURE__ */ new Error(`client:register rejected: ${msg.message ?? "unknown"}`);
|
|
1520
|
+
this.wsLogger.error({ message: msg.message }, "client register rejected");
|
|
1364
1521
|
this.emit("error", err);
|
|
1365
1522
|
this.ws?.close(4403, "register rejected");
|
|
1366
1523
|
return;
|
|
@@ -1369,6 +1526,7 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1369
1526
|
const isReconnect = this.boundAgents.size > 0 || this.desiredBindings.size > 0;
|
|
1370
1527
|
this.registered = true;
|
|
1371
1528
|
this.startHeartbeat();
|
|
1529
|
+
this.wsLogger.info({ isReconnect }, "registered");
|
|
1372
1530
|
this.emit("connected");
|
|
1373
1531
|
connectResolve?.();
|
|
1374
1532
|
if (isReconnect) this.rebindAgents();
|
|
@@ -1476,6 +1634,10 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1476
1634
|
this.reconnectAttempt++;
|
|
1477
1635
|
this.emit("reconnecting", this.reconnectAttempt);
|
|
1478
1636
|
const delay = Math.min(RECONNECT_BASE_MS * 2 ** (this.reconnectAttempt - 1), RECONNECT_MAX_MS);
|
|
1637
|
+
this.wsLogger.debug({
|
|
1638
|
+
attempt: this.reconnectAttempt,
|
|
1639
|
+
delayMs: delay
|
|
1640
|
+
}, "scheduling reconnect");
|
|
1479
1641
|
this.reconnectTimer = setTimeout(() => {
|
|
1480
1642
|
this.reconnectTimer = null;
|
|
1481
1643
|
if (!this.closing) this.openWebSocket().catch((err) => {
|
|
@@ -1531,9 +1693,11 @@ var ClientConnection = class extends EventEmitter {
|
|
|
1531
1693
|
if (!exp) return;
|
|
1532
1694
|
const delay = exp * 1e3 - Date.now() - AUTH_REFRESH_LEAD_MS;
|
|
1533
1695
|
if (delay <= 0) return;
|
|
1696
|
+
this.authLogger.debug({ delayMs: delay }, "scheduled proactive auth refresh");
|
|
1534
1697
|
this.authRefreshTimer = setTimeout(() => {
|
|
1535
1698
|
this.authRefreshTimer = null;
|
|
1536
1699
|
if (this.closing) return;
|
|
1700
|
+
this.authLogger.info("triggering proactive auth refresh");
|
|
1537
1701
|
this.ws?.close(1e3, "proactive auth refresh");
|
|
1538
1702
|
}, delay);
|
|
1539
1703
|
}
|
|
@@ -1890,7 +2054,7 @@ function looksLikeCommitSha(ref) {
|
|
|
1890
2054
|
function createGitMirrorManager(opts) {
|
|
1891
2055
|
const mirrorsRoot = join(opts.dataDir, "git-mirrors");
|
|
1892
2056
|
const cloneTimeoutMs = opts.cloneTimeoutMs ?? Number(process.env.FIRST_TREE_HUB_GIT_CLONE_TIMEOUT_MS ?? DEFAULT_CLONE_TIMEOUT_MS);
|
|
1893
|
-
const log = opts.log
|
|
2057
|
+
const log = opts.log;
|
|
1894
2058
|
const urlLocks = /* @__PURE__ */ new Map();
|
|
1895
2059
|
function withUrlLock(url, op) {
|
|
1896
2060
|
const key = hashUrl(url);
|
|
@@ -2033,7 +2197,7 @@ function createGitMirrorManager(opts) {
|
|
|
2033
2197
|
"origin",
|
|
2034
2198
|
"--auto"
|
|
2035
2199
|
], mirrorPath, 3e4);
|
|
2036
|
-
log(
|
|
2200
|
+
log?.info({ gitUrl: url }, "mirror config migrated");
|
|
2037
2201
|
}
|
|
2038
2202
|
return { migrated };
|
|
2039
2203
|
}
|
|
@@ -2137,22 +2301,22 @@ function createGitMirrorManager(opts) {
|
|
|
2137
2301
|
try {
|
|
2138
2302
|
await bootstrapMirror(path, url);
|
|
2139
2303
|
const elapsedMs = Date.now() - start;
|
|
2140
|
-
log(
|
|
2304
|
+
log?.debug({
|
|
2141
2305
|
gitUrl: url,
|
|
2142
2306
|
elapsedMs,
|
|
2143
2307
|
cloned: true
|
|
2144
|
-
});
|
|
2308
|
+
}, "mirror ensured");
|
|
2145
2309
|
return {
|
|
2146
2310
|
mirrorPath: path,
|
|
2147
2311
|
elapsedMs,
|
|
2148
2312
|
cloned: true
|
|
2149
2313
|
};
|
|
2150
2314
|
} catch (err) {
|
|
2151
|
-
if (err instanceof GitMirrorTimeoutError) log(
|
|
2315
|
+
if (err instanceof GitMirrorTimeoutError) log?.warn({
|
|
2152
2316
|
gitUrl: url,
|
|
2153
2317
|
timeoutMs: cloneTimeoutMs,
|
|
2154
2318
|
elapsedMs: cloneTimeoutMs
|
|
2155
|
-
});
|
|
2319
|
+
}, "mirror clone timeout");
|
|
2156
2320
|
if (existsSync(path)) rmSync(path, {
|
|
2157
2321
|
recursive: true,
|
|
2158
2322
|
force: true
|
|
@@ -2173,11 +2337,11 @@ function createGitMirrorManager(opts) {
|
|
|
2173
2337
|
], path, cloneTimeoutMs);
|
|
2174
2338
|
return { elapsedMs };
|
|
2175
2339
|
} catch (err) {
|
|
2176
|
-
log(
|
|
2340
|
+
log?.warn({
|
|
2177
2341
|
gitUrl: url,
|
|
2178
2342
|
errorCode: err instanceof GitMirrorError ? "git-failed" : "unknown",
|
|
2179
2343
|
stderr: err instanceof Error ? err.message.slice(0, 1024) : String(err).slice(0, 1024)
|
|
2180
|
-
});
|
|
2344
|
+
}, "mirror fetch failed");
|
|
2181
2345
|
throw err;
|
|
2182
2346
|
}
|
|
2183
2347
|
});
|
|
@@ -2189,11 +2353,11 @@ function createGitMirrorManager(opts) {
|
|
|
2189
2353
|
const absTarget = resolve(targetPath);
|
|
2190
2354
|
const branchName = deriveSessionBranchName(sessionKey, url);
|
|
2191
2355
|
if (existsSync(absTarget) && !isHubManagedWorktree(absTarget)) {
|
|
2192
|
-
log(
|
|
2356
|
+
log?.warn({
|
|
2193
2357
|
gitUrl: url,
|
|
2194
2358
|
targetPath: absTarget,
|
|
2195
2359
|
occupantKind: classifyOccupant(absTarget)
|
|
2196
|
-
});
|
|
2360
|
+
}, "worktree create conflict");
|
|
2197
2361
|
throw new GitMirrorWorktreeConflictError(`Worktree target "${absTarget}" is already occupied by ${classifyOccupant(absTarget)} — aborting (D13)`);
|
|
2198
2362
|
}
|
|
2199
2363
|
const pathExists = existsSync(absTarget);
|
|
@@ -2409,6 +2573,17 @@ function cleanWorkspaces(workspaceRoot, activeChatIds, ttlMs = DEFAULT_WORKSPACE
|
|
|
2409
2573
|
const MAX_RETRIES = 2;
|
|
2410
2574
|
const TOOL_RESULT_PREVIEW_LIMIT = 400;
|
|
2411
2575
|
const ASSISTANT_TEXT_EVENT_LIMIT = 8e3;
|
|
2576
|
+
const SUPPORTED_IMAGE_MIMES = new Set([
|
|
2577
|
+
"image/png",
|
|
2578
|
+
"image/jpeg",
|
|
2579
|
+
"image/gif",
|
|
2580
|
+
"image/webp"
|
|
2581
|
+
]);
|
|
2582
|
+
function isImageFileContent(content) {
|
|
2583
|
+
if (!content || typeof content !== "object") return false;
|
|
2584
|
+
const c = content;
|
|
2585
|
+
return typeof c.data === "string" && typeof c.mimeType === "string" && typeof c.filename === "string" && SUPPORTED_IMAGE_MIMES.has(c.mimeType);
|
|
2586
|
+
}
|
|
2412
2587
|
function extractContentBlocks(message) {
|
|
2413
2588
|
if (!message || typeof message !== "object") return [];
|
|
2414
2589
|
const inner = message.message;
|
|
@@ -2581,6 +2756,28 @@ const createClaudeCodeHandler = (config) => {
|
|
|
2581
2756
|
/** Worktrees materialised for this session — each entry removed on shutdown. */
|
|
2582
2757
|
const ownedWorktrees = [];
|
|
2583
2758
|
function toSDKUserMessage(message, sessionId) {
|
|
2759
|
+
if (message.format === "file" && isImageFileContent(message.content)) {
|
|
2760
|
+
const { data, mimeType, filename } = message.content;
|
|
2761
|
+
return {
|
|
2762
|
+
type: "user",
|
|
2763
|
+
message: {
|
|
2764
|
+
role: "user",
|
|
2765
|
+
content: [{
|
|
2766
|
+
type: "text",
|
|
2767
|
+
text: `${message.senderId ? `[From: ${message.senderId}]\n\n` : ""}[Attached image: ${filename}]`
|
|
2768
|
+
}, {
|
|
2769
|
+
type: "image",
|
|
2770
|
+
source: {
|
|
2771
|
+
type: "base64",
|
|
2772
|
+
media_type: mimeType,
|
|
2773
|
+
data
|
|
2774
|
+
}
|
|
2775
|
+
}]
|
|
2776
|
+
},
|
|
2777
|
+
parent_tool_use_id: null,
|
|
2778
|
+
session_id: sessionId
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2584
2781
|
const rawContent = typeof message.content === "string" ? message.content : JSON.stringify(message.content);
|
|
2585
2782
|
return {
|
|
2586
2783
|
type: "user",
|
|
@@ -2997,7 +3194,7 @@ function registerBuiltinHandlers() {
|
|
|
2997
3194
|
}
|
|
2998
3195
|
function createAgentConfigCache(opts) {
|
|
2999
3196
|
const { sdk } = opts;
|
|
3000
|
-
const log = opts.log
|
|
3197
|
+
const log = opts.log;
|
|
3001
3198
|
const entries = /* @__PURE__ */ new Map();
|
|
3002
3199
|
function urlsFromConfig(cfg) {
|
|
3003
3200
|
return new Set(cfg.payload.gitRepos.map((r) => r.url));
|
|
@@ -3042,7 +3239,10 @@ function createAgentConfigCache(opts) {
|
|
|
3042
3239
|
};
|
|
3043
3240
|
slot.inflight = doFetch(agentId).catch((err) => {
|
|
3044
3241
|
slot.inflight = null;
|
|
3045
|
-
log(
|
|
3242
|
+
log?.warn({
|
|
3243
|
+
agentId,
|
|
3244
|
+
err
|
|
3245
|
+
}, "agent config fetch failed");
|
|
3046
3246
|
throw err;
|
|
3047
3247
|
});
|
|
3048
3248
|
entries.set(agentId, slot);
|
|
@@ -3212,13 +3412,21 @@ var SessionManager = class {
|
|
|
3212
3412
|
const chatId = entry.chatId ?? entry.message.chatId;
|
|
3213
3413
|
const messageId = entry.message.id;
|
|
3214
3414
|
if (this.deduplicator.isDuplicate(messageId)) {
|
|
3215
|
-
this.config.log(
|
|
3415
|
+
this.config.log.debug({
|
|
3416
|
+
chatId,
|
|
3417
|
+
messageId
|
|
3418
|
+
}, "duplicate message, skipping");
|
|
3216
3419
|
return;
|
|
3217
3420
|
}
|
|
3218
3421
|
if (this.config.agentConfigCache) try {
|
|
3219
3422
|
await this.config.agentConfigCache.refreshIfNewer(this.config.agentIdentity.agentId, entry.message.configVersion);
|
|
3220
3423
|
} catch (err) {
|
|
3221
|
-
this.config.log(
|
|
3424
|
+
this.config.log.warn({
|
|
3425
|
+
chatId,
|
|
3426
|
+
agentId: this.config.agentIdentity.agentId,
|
|
3427
|
+
incomingVersion: entry.message.configVersion,
|
|
3428
|
+
err
|
|
3429
|
+
}, "config version mismatch — skipping refresh");
|
|
3222
3430
|
}
|
|
3223
3431
|
const message = this.extractMessage(entry);
|
|
3224
3432
|
await this.routeMessage(chatId, message, entry.id);
|
|
@@ -3228,7 +3436,7 @@ var SessionManager = class {
|
|
|
3228
3436
|
if (command === "session:suspend") {
|
|
3229
3437
|
const session = this.sessions.get(chatId);
|
|
3230
3438
|
if (session?.status === "active") {
|
|
3231
|
-
this.config.log(
|
|
3439
|
+
this.config.log.info({ chatId }, "suspend command received");
|
|
3232
3440
|
this.suspendSession(session);
|
|
3233
3441
|
}
|
|
3234
3442
|
return;
|
|
@@ -3237,7 +3445,7 @@ var SessionManager = class {
|
|
|
3237
3445
|
const session = this.sessions.get(chatId);
|
|
3238
3446
|
const hadMapping = this.evictedMappings.has(chatId);
|
|
3239
3447
|
if (!session && !hadMapping) return;
|
|
3240
|
-
this.config.log(
|
|
3448
|
+
this.config.log.info({ chatId }, "terminate command received");
|
|
3241
3449
|
if (session?.status === "active") {
|
|
3242
3450
|
this._activeCount--;
|
|
3243
3451
|
await session.handler.shutdown().catch(() => {});
|
|
@@ -3322,7 +3530,7 @@ var SessionManager = class {
|
|
|
3322
3530
|
await this.ackEntry(entryId, chatId);
|
|
3323
3531
|
existing.handler.inject(message);
|
|
3324
3532
|
existing.lastActivity = Date.now();
|
|
3325
|
-
this.config.log(
|
|
3533
|
+
this.config.log.debug({ chatId }, "message injected");
|
|
3326
3534
|
return;
|
|
3327
3535
|
case "suspended":
|
|
3328
3536
|
case "evicted":
|
|
@@ -3357,16 +3565,26 @@ var SessionManager = class {
|
|
|
3357
3565
|
if (evicted) {
|
|
3358
3566
|
const sessionId = await handler.resume(message, evicted.claudeSessionId, ctx);
|
|
3359
3567
|
entry.claudeSessionId = sessionId;
|
|
3360
|
-
this.config.log(
|
|
3568
|
+
this.config.log.info({
|
|
3569
|
+
chatId,
|
|
3570
|
+
sessionId
|
|
3571
|
+
}, "session resumed from eviction");
|
|
3361
3572
|
} else {
|
|
3362
3573
|
const sessionId = await handler.start(message, ctx);
|
|
3363
3574
|
entry.claudeSessionId = sessionId;
|
|
3364
|
-
this.config.log(
|
|
3575
|
+
this.config.log.info({
|
|
3576
|
+
chatId,
|
|
3577
|
+
sessionId
|
|
3578
|
+
}, "session created");
|
|
3365
3579
|
}
|
|
3366
3580
|
this.persistRegistry();
|
|
3367
3581
|
this.notifySessionState(chatId, "active");
|
|
3368
3582
|
} catch (err) {
|
|
3369
|
-
this.config.log(
|
|
3583
|
+
this.config.log.error({
|
|
3584
|
+
chatId,
|
|
3585
|
+
err,
|
|
3586
|
+
phase: evicted ? "resume" : "start"
|
|
3587
|
+
}, "session start/resume failed");
|
|
3370
3588
|
this.sessions.delete(chatId);
|
|
3371
3589
|
this.sessionRuntimeStates.delete(chatId);
|
|
3372
3590
|
this.recomputeRuntimeState();
|
|
@@ -3391,11 +3609,17 @@ var SessionManager = class {
|
|
|
3391
3609
|
entry.lastActivity = Date.now();
|
|
3392
3610
|
try {
|
|
3393
3611
|
await entry.handler.resume(message ?? void 0, entry.claudeSessionId, ctx);
|
|
3394
|
-
this.config.log
|
|
3612
|
+
this.config.log.info({
|
|
3613
|
+
chatId: entry.chatId,
|
|
3614
|
+
sessionId: entry.claudeSessionId
|
|
3615
|
+
}, "session resumed");
|
|
3395
3616
|
this.persistRegistry();
|
|
3396
3617
|
this.notifySessionState(entry.chatId, "active");
|
|
3397
3618
|
} catch (err) {
|
|
3398
|
-
this.config.log(
|
|
3619
|
+
this.config.log.warn({
|
|
3620
|
+
chatId: entry.chatId,
|
|
3621
|
+
err
|
|
3622
|
+
}, "resume failed");
|
|
3399
3623
|
entry.status = "suspended";
|
|
3400
3624
|
this._activeCount--;
|
|
3401
3625
|
}
|
|
@@ -3416,11 +3640,11 @@ var SessionManager = class {
|
|
|
3416
3640
|
if (!oldestActive || session.lastActivity < oldestActive.lastActivity) oldestActive = session;
|
|
3417
3641
|
}
|
|
3418
3642
|
if (oldestActive) {
|
|
3419
|
-
this.config.log(
|
|
3643
|
+
this.config.log.info({ chatId: oldestActive.chatId }, "session preempted for concurrency");
|
|
3420
3644
|
this.suspendSession(oldestActive);
|
|
3421
3645
|
return true;
|
|
3422
3646
|
}
|
|
3423
|
-
this.config.log(
|
|
3647
|
+
this.config.log.info({ chatId }, "concurrency limit reached, queuing");
|
|
3424
3648
|
this.pendingQueue.push({
|
|
3425
3649
|
message,
|
|
3426
3650
|
chatId,
|
|
@@ -3434,7 +3658,10 @@ var SessionManager = class {
|
|
|
3434
3658
|
this.sessionRuntimeStates.delete(entry.chatId);
|
|
3435
3659
|
this.recomputeRuntimeState();
|
|
3436
3660
|
entry.suspending = entry.handler.suspend().catch((err) => {
|
|
3437
|
-
this.config.log(
|
|
3661
|
+
this.config.log.warn({
|
|
3662
|
+
chatId: entry.chatId,
|
|
3663
|
+
err
|
|
3664
|
+
}, "suspend error");
|
|
3438
3665
|
}).finally(() => {
|
|
3439
3666
|
entry.suspending = null;
|
|
3440
3667
|
});
|
|
@@ -3448,7 +3675,10 @@ var SessionManager = class {
|
|
|
3448
3675
|
const next = this.pendingQueue.shift();
|
|
3449
3676
|
if (!next) return;
|
|
3450
3677
|
this.routeMessage(next.chatId, next.message, next.entryId > 0 ? next.entryId : void 0).catch((err) => {
|
|
3451
|
-
this.config.log(
|
|
3678
|
+
this.config.log.warn({
|
|
3679
|
+
chatId: next.chatId,
|
|
3680
|
+
err
|
|
3681
|
+
}, "pending drain error");
|
|
3452
3682
|
});
|
|
3453
3683
|
}
|
|
3454
3684
|
evictIfNeeded() {
|
|
@@ -3475,7 +3705,7 @@ var SessionManager = class {
|
|
|
3475
3705
|
claudeSessionId: candidate.session.claudeSessionId,
|
|
3476
3706
|
lastActivity: candidate.session.lastActivity
|
|
3477
3707
|
});
|
|
3478
|
-
this.config.log(
|
|
3708
|
+
this.config.log.info({ chatId: candidate.key }, "session evicted (max_sessions reached)");
|
|
3479
3709
|
if (candidate.session.status === "active") {
|
|
3480
3710
|
this._activeCount--;
|
|
3481
3711
|
candidate.session.handler.shutdown().catch(() => {});
|
|
@@ -3494,11 +3724,17 @@ var SessionManager = class {
|
|
|
3494
3724
|
if (session.status !== "active") continue;
|
|
3495
3725
|
const inactiveMs = now - session.lastActivity;
|
|
3496
3726
|
if (inactiveMs > timeoutMs) {
|
|
3497
|
-
this.config.log(
|
|
3727
|
+
this.config.log.info({
|
|
3728
|
+
chatId: session.chatId,
|
|
3729
|
+
idleTimeoutSec: this.config.session.idle_timeout
|
|
3730
|
+
}, "session idle, suspending");
|
|
3498
3731
|
this.suspendSession(session);
|
|
3499
3732
|
} else if (inactiveMs > blockedThresholdMs) {
|
|
3500
3733
|
if (this.sessionRuntimeStates.get(session.chatId) === "working") {
|
|
3501
|
-
this.config.log(
|
|
3734
|
+
this.config.log.warn({
|
|
3735
|
+
chatId: session.chatId,
|
|
3736
|
+
inactiveSec: Math.round(inactiveMs / 1e3)
|
|
3737
|
+
}, "session working but no output, marking blocked");
|
|
3502
3738
|
this.setSessionRuntimeState(session.chatId, "blocked");
|
|
3503
3739
|
}
|
|
3504
3740
|
}
|
|
@@ -3525,14 +3761,18 @@ var SessionManager = class {
|
|
|
3525
3761
|
try {
|
|
3526
3762
|
await this.config.sdk.ack(entryId);
|
|
3527
3763
|
} catch {
|
|
3528
|
-
this.config.log(
|
|
3764
|
+
this.config.log.warn({
|
|
3765
|
+
chatId,
|
|
3766
|
+
entryId
|
|
3767
|
+
}, "ACK failed, continuing");
|
|
3529
3768
|
}
|
|
3530
3769
|
}
|
|
3531
3770
|
buildSessionContext(chatId) {
|
|
3771
|
+
const sessionLog = this.config.log.child({ chatId });
|
|
3532
3772
|
return {
|
|
3533
3773
|
agent: this.config.agentIdentity,
|
|
3534
3774
|
sdk: this.config.sdk,
|
|
3535
|
-
log: (msg) =>
|
|
3775
|
+
log: (msg) => sessionLog.info(msg),
|
|
3536
3776
|
chatId,
|
|
3537
3777
|
touch: () => {
|
|
3538
3778
|
const entry = this.sessions.get(chatId);
|
|
@@ -3591,7 +3831,7 @@ var SessionManager = class {
|
|
|
3591
3831
|
claudeSessionId: data.claudeSessionId,
|
|
3592
3832
|
lastActivity: data.lastActivity
|
|
3593
3833
|
});
|
|
3594
|
-
if (persisted.size > 0) this.config.log(
|
|
3834
|
+
if (persisted.size > 0) this.config.log.info({ count: persisted.size }, "loaded persisted session mappings");
|
|
3595
3835
|
}
|
|
3596
3836
|
persistRegistry() {
|
|
3597
3837
|
if (!this.registry) return;
|
|
@@ -3612,7 +3852,7 @@ var SessionManager = class {
|
|
|
3612
3852
|
var AgentSlot = class {
|
|
3613
3853
|
sessionManager = null;
|
|
3614
3854
|
config;
|
|
3615
|
-
|
|
3855
|
+
logger;
|
|
3616
3856
|
sdk = null;
|
|
3617
3857
|
agentConfigCache = null;
|
|
3618
3858
|
pollingTimer = null;
|
|
@@ -3620,9 +3860,10 @@ var AgentSlot = class {
|
|
|
3620
3860
|
listeners = [];
|
|
3621
3861
|
constructor(config) {
|
|
3622
3862
|
this.config = config;
|
|
3623
|
-
this.
|
|
3624
|
-
|
|
3625
|
-
|
|
3863
|
+
this.logger = createLogger("slot").child({
|
|
3864
|
+
agentName: config.name,
|
|
3865
|
+
agentId: config.agentId
|
|
3866
|
+
});
|
|
3626
3867
|
}
|
|
3627
3868
|
get clientConnection() {
|
|
3628
3869
|
return this.config.clientConnection;
|
|
@@ -3642,21 +3883,21 @@ var AgentSlot = class {
|
|
|
3642
3883
|
const sdk = (await this.clientConnection.bindAgent(this.config.agentId, this.config.runtimeType ?? this.config.type, this.config.runtimeVersion)).sdk;
|
|
3643
3884
|
this.sdk = sdk;
|
|
3644
3885
|
const agent = await sdk.register();
|
|
3645
|
-
this.
|
|
3886
|
+
this.logger.info({ displayName: agent.displayName ?? agent.agentId }, "agent bound");
|
|
3646
3887
|
if (agent.type === "human") {
|
|
3647
|
-
this.
|
|
3888
|
+
this.logger.info("server reports type=human — message processing disabled");
|
|
3648
3889
|
return agent;
|
|
3649
3890
|
}
|
|
3650
3891
|
this.agentConfigCache = createAgentConfigCache({
|
|
3651
3892
|
sdk,
|
|
3652
|
-
log: this.
|
|
3893
|
+
log: this.logger
|
|
3653
3894
|
});
|
|
3654
3895
|
try {
|
|
3655
3896
|
const cfg = await this.agentConfigCache.refresh(agent.agentId);
|
|
3656
|
-
this.
|
|
3897
|
+
this.logger.info({ version: cfg.version }, "runtime config loaded");
|
|
3657
3898
|
} catch (err) {
|
|
3658
3899
|
const msg = err instanceof Error ? err.message : String(err);
|
|
3659
|
-
this.
|
|
3900
|
+
this.logger.error({ err }, "failed to fetch agent config — bind aborted");
|
|
3660
3901
|
throw new Error(`Hub unreachable while loading agent config: ${msg}`);
|
|
3661
3902
|
}
|
|
3662
3903
|
const onMessage = (agentId) => {
|
|
@@ -3687,7 +3928,10 @@ var AgentSlot = class {
|
|
|
3687
3928
|
const registryPath = join(DEFAULT_DATA_DIR, "sessions", `${this.config.name}.json`);
|
|
3688
3929
|
const gitMirrorManager = createGitMirrorManager({
|
|
3689
3930
|
dataDir: DEFAULT_DATA_DIR,
|
|
3690
|
-
log: (
|
|
3931
|
+
log: createLogger("git-mirror").child({
|
|
3932
|
+
agentName: this.config.name,
|
|
3933
|
+
agentId: this.config.agentId
|
|
3934
|
+
})
|
|
3691
3935
|
});
|
|
3692
3936
|
this.sessionManager = new SessionManager({
|
|
3693
3937
|
session: this.config.session,
|
|
@@ -3706,7 +3950,7 @@ var AgentSlot = class {
|
|
|
3706
3950
|
metadata: agent.metadata
|
|
3707
3951
|
},
|
|
3708
3952
|
sdk,
|
|
3709
|
-
log: this.
|
|
3953
|
+
log: this.logger,
|
|
3710
3954
|
registryPath,
|
|
3711
3955
|
agentConfigCache: this.agentConfigCache,
|
|
3712
3956
|
onStateChange: (chatId, state) => this.reportSessionState(chatId, state),
|
|
@@ -3716,7 +3960,11 @@ var AgentSlot = class {
|
|
|
3716
3960
|
});
|
|
3717
3961
|
const onCommand = (cmd) => {
|
|
3718
3962
|
if (cmd.agentId === this.config.agentId && this.sessionManager) this.sessionManager.handleCommand(cmd.chatId, cmd.type).catch((err) => {
|
|
3719
|
-
this.
|
|
3963
|
+
this.logger.error({
|
|
3964
|
+
err,
|
|
3965
|
+
chatId: cmd.chatId,
|
|
3966
|
+
type: cmd.type
|
|
3967
|
+
}, "session command error");
|
|
3720
3968
|
});
|
|
3721
3969
|
};
|
|
3722
3970
|
this.clientConnection.on("session:command", onCommand);
|
|
@@ -3744,7 +3992,7 @@ var AgentSlot = class {
|
|
|
3744
3992
|
this.listeners = [];
|
|
3745
3993
|
await this.clientConnection.unbindAgent(this.config.agentId);
|
|
3746
3994
|
await this.sessionManager?.shutdown();
|
|
3747
|
-
this.
|
|
3995
|
+
this.logger.info("stopped");
|
|
3748
3996
|
}
|
|
3749
3997
|
reportSessionState(chatId, state) {
|
|
3750
3998
|
this.clientConnection.reportSessionState(this.config.agentId, chatId, state);
|
|
@@ -3786,7 +4034,7 @@ var AgentSlot = class {
|
|
|
3786
4034
|
const { entries } = await this.sdk.pull(10);
|
|
3787
4035
|
for (const entry of entries) await this.sessionManager.dispatch(entry);
|
|
3788
4036
|
} catch (err) {
|
|
3789
|
-
this.
|
|
4037
|
+
this.logger.warn({ err }, "poll error");
|
|
3790
4038
|
}
|
|
3791
4039
|
}
|
|
3792
4040
|
};
|
|
@@ -3963,6 +4211,71 @@ function sleep(ms) {
|
|
|
3963
4211
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3964
4212
|
}
|
|
3965
4213
|
//#endregion
|
|
4214
|
+
//#region src/core/output.ts
|
|
4215
|
+
/**
|
|
4216
|
+
* Print layer — the only place CLI code should write to stdout/stderr.
|
|
4217
|
+
*
|
|
4218
|
+
* Contract:
|
|
4219
|
+
* - `print.result(data)` / `print.fail(...)` emit machine-readable JSON on
|
|
4220
|
+
* stdout / stderr respectively. Scripts pipe into `jq` and expect a clean
|
|
4221
|
+
* envelope, so nothing else may touch stdout.
|
|
4222
|
+
* - `print.status` / `print.check` / `print.blank` / `print.line` are
|
|
4223
|
+
* human-friendly and go to stderr so they never pollute a redirected stdout.
|
|
4224
|
+
* In `--json` mode they are silenced — scripted consumers only care about
|
|
4225
|
+
* the envelope.
|
|
4226
|
+
*/
|
|
4227
|
+
let jsonMode = false;
|
|
4228
|
+
function setJsonMode(enabled) {
|
|
4229
|
+
jsonMode = enabled;
|
|
4230
|
+
}
|
|
4231
|
+
function result(data) {
|
|
4232
|
+
process.stdout.write(`${JSON.stringify({
|
|
4233
|
+
ok: true,
|
|
4234
|
+
data
|
|
4235
|
+
})}\n`);
|
|
4236
|
+
}
|
|
4237
|
+
function fail(code, message, exitCode = 1) {
|
|
4238
|
+
process.stderr.write(`${JSON.stringify({
|
|
4239
|
+
ok: false,
|
|
4240
|
+
error: {
|
|
4241
|
+
code,
|
|
4242
|
+
message
|
|
4243
|
+
}
|
|
4244
|
+
})}\n`);
|
|
4245
|
+
process.exit(exitCode);
|
|
4246
|
+
}
|
|
4247
|
+
function status(label, message) {
|
|
4248
|
+
if (jsonMode) return;
|
|
4249
|
+
process.stderr.write(` ${label.padEnd(20)} ${message}\n`);
|
|
4250
|
+
}
|
|
4251
|
+
function check(pass, label, detail = "") {
|
|
4252
|
+
if (jsonMode) return;
|
|
4253
|
+
const icon = pass ? "✓" : "✗";
|
|
4254
|
+
const tail = detail ? ` ${detail}` : "";
|
|
4255
|
+
process.stderr.write(` ${icon} ${label.padEnd(22)}${tail}\n`);
|
|
4256
|
+
}
|
|
4257
|
+
function blank() {
|
|
4258
|
+
if (jsonMode) return;
|
|
4259
|
+
process.stderr.write("\n");
|
|
4260
|
+
}
|
|
4261
|
+
/**
|
|
4262
|
+
* Generic stderr writer for pre-formatted human text (multi-line tables,
|
|
4263
|
+
* interactive prompts). Prefer `status` / `check` when the text fits; this
|
|
4264
|
+
* exists so the `--json` mode gate can silence arbitrary human chatter.
|
|
4265
|
+
*/
|
|
4266
|
+
function line(text) {
|
|
4267
|
+
if (jsonMode) return;
|
|
4268
|
+
process.stderr.write(text);
|
|
4269
|
+
}
|
|
4270
|
+
const print = {
|
|
4271
|
+
result,
|
|
4272
|
+
fail,
|
|
4273
|
+
status,
|
|
4274
|
+
check,
|
|
4275
|
+
blank,
|
|
4276
|
+
line
|
|
4277
|
+
};
|
|
4278
|
+
//#endregion
|
|
3966
4279
|
//#region src/core/admin.ts
|
|
3967
4280
|
/**
|
|
3968
4281
|
* Check if any user exists.
|
|
@@ -4083,10 +4396,10 @@ var ClientRuntime = class {
|
|
|
4083
4396
|
});
|
|
4084
4397
|
registerBuiltinHandlers();
|
|
4085
4398
|
this.connection.on("auth:expired", () => {
|
|
4086
|
-
|
|
4399
|
+
print.status("⚠️", "access token expired — reconnecting after refresh...");
|
|
4087
4400
|
});
|
|
4088
4401
|
this.connection.on("error", (err) => {
|
|
4089
|
-
|
|
4402
|
+
print.status("⚠️", `client connection error: ${err.message}`);
|
|
4090
4403
|
});
|
|
4091
4404
|
this.connection.on("agent:pinned", (message) => {
|
|
4092
4405
|
this.handleAgentPinned(message);
|
|
@@ -4121,27 +4434,30 @@ var ClientRuntime = class {
|
|
|
4121
4434
|
currentVersion: this.options.currentVersion,
|
|
4122
4435
|
...this.options.update,
|
|
4123
4436
|
isTTY: Boolean(process.stdout.isTTY),
|
|
4124
|
-
log: (level, msg) =>
|
|
4437
|
+
log: (level, msg) => print.status(`[update/${level}]`, msg),
|
|
4125
4438
|
getQuietGateSnapshot: () => this.aggregateQuietGate()
|
|
4126
4439
|
});
|
|
4127
4440
|
await this.connection.connect();
|
|
4128
|
-
|
|
4441
|
+
print.check(true, "client registered", this.connection.clientId);
|
|
4129
4442
|
if (this.agents.length === 0) {
|
|
4130
|
-
|
|
4131
|
-
|
|
4443
|
+
print.blank();
|
|
4444
|
+
print.status("", "no agents configured yet.");
|
|
4445
|
+
print.status("", "add one with: first-tree-hub agent create <name> --type claude-code --client-id <id>");
|
|
4446
|
+
print.blank();
|
|
4132
4447
|
return;
|
|
4133
4448
|
}
|
|
4134
4449
|
await Promise.allSettled(this.agents.map(async (agent) => {
|
|
4135
4450
|
try {
|
|
4136
4451
|
const identity = await agent.slot.start();
|
|
4137
|
-
|
|
4452
|
+
print.check(true, `${agent.name}: connected`, `agent: ${identity.displayName ?? identity.agentId}`);
|
|
4138
4453
|
} catch (error) {
|
|
4139
4454
|
const msg = error instanceof Error ? error.message : String(error);
|
|
4140
|
-
|
|
4455
|
+
print.check(false, `${agent.name}: connection failed`, msg);
|
|
4141
4456
|
}
|
|
4142
4457
|
}));
|
|
4143
4458
|
const connected = this.agents.length;
|
|
4144
|
-
|
|
4459
|
+
print.blank();
|
|
4460
|
+
print.status("", `${connected} agent(s) running. Press Ctrl+C to stop.`);
|
|
4145
4461
|
}
|
|
4146
4462
|
watchAgentsDir(agentsDir) {
|
|
4147
4463
|
this.agentsDir = agentsDir;
|
|
@@ -4194,7 +4510,8 @@ var ClientRuntime = class {
|
|
|
4194
4510
|
for (const [name, config] of all) {
|
|
4195
4511
|
if (this.agentNames.has(name)) continue;
|
|
4196
4512
|
if (this.agentIds.has(config.agentId)) continue;
|
|
4197
|
-
|
|
4513
|
+
print.blank();
|
|
4514
|
+
print.status("", `new agent detected: ${name}`);
|
|
4198
4515
|
this.addAgent(name, config);
|
|
4199
4516
|
this.startAgent(name);
|
|
4200
4517
|
}
|
|
@@ -4209,7 +4526,7 @@ var ClientRuntime = class {
|
|
|
4209
4526
|
handleAgentPinned(message) {
|
|
4210
4527
|
if (this.agentIds.has(message.agentId)) return;
|
|
4211
4528
|
if (!this.agentsDir) {
|
|
4212
|
-
|
|
4529
|
+
print.status("⚠️", `agent pinned (${message.agentId}) but no agents dir set — cannot auto-register.`);
|
|
4213
4530
|
return;
|
|
4214
4531
|
}
|
|
4215
4532
|
const localName = this.pickLocalName(message);
|
|
@@ -4224,10 +4541,10 @@ var ClientRuntime = class {
|
|
|
4224
4541
|
runtime: "claude-code"
|
|
4225
4542
|
});
|
|
4226
4543
|
writeFileSync(join(agentDir, "agent.yaml"), yaml, { mode: 384 });
|
|
4227
|
-
|
|
4544
|
+
print.check(true, `auto-added agent "${localName}"`, `${message.agentId} (from server push)`);
|
|
4228
4545
|
} catch (err) {
|
|
4229
4546
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4230
|
-
|
|
4547
|
+
print.check(false, `failed to auto-add agent "${localName}"`, msg);
|
|
4231
4548
|
return;
|
|
4232
4549
|
}
|
|
4233
4550
|
this.scanForNewAgents(this.agentsDir);
|
|
@@ -4259,10 +4576,10 @@ var ClientRuntime = class {
|
|
|
4259
4576
|
const entry = this.agents.find((a) => a.name === name);
|
|
4260
4577
|
if (!entry) return;
|
|
4261
4578
|
entry.slot.start().then((identity) => {
|
|
4262
|
-
|
|
4579
|
+
print.check(true, `${name}: connected`, `agent: ${identity.displayName ?? identity.agentId}`);
|
|
4263
4580
|
}).catch((err) => {
|
|
4264
4581
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4265
|
-
|
|
4582
|
+
print.check(false, `${name}: connection failed`, msg);
|
|
4266
4583
|
});
|
|
4267
4584
|
}
|
|
4268
4585
|
};
|
|
@@ -4441,16 +4758,6 @@ function getContainerPassword() {
|
|
|
4441
4758
|
throw new Error("Cannot determine PostgreSQL password from container");
|
|
4442
4759
|
}
|
|
4443
4760
|
//#endregion
|
|
4444
|
-
//#region src/core/output.ts
|
|
4445
|
-
/** Print a styled status line to stderr (human-friendly output). */
|
|
4446
|
-
function status(label, message) {
|
|
4447
|
-
process.stderr.write(` ${label.padEnd(20)} ${message}\n`);
|
|
4448
|
-
}
|
|
4449
|
-
/** Print a blank line to stderr. */
|
|
4450
|
-
function blank() {
|
|
4451
|
-
process.stderr.write("\n");
|
|
4452
|
-
}
|
|
4453
|
-
//#endregion
|
|
4454
4761
|
//#region src/core/doctor.ts
|
|
4455
4762
|
function getServerConfig() {
|
|
4456
4763
|
return resolveConfigReadonly({
|
|
@@ -4691,12 +4998,12 @@ async function checkWebSocket() {
|
|
|
4691
4998
|
function printResults(results) {
|
|
4692
4999
|
for (const r of results) {
|
|
4693
5000
|
const icon = r.ok ? "✓" : "✗";
|
|
4694
|
-
|
|
5001
|
+
print.line(` ${icon} ${r.label.padEnd(22)} ${r.detail}\n`);
|
|
4695
5002
|
}
|
|
4696
5003
|
blank();
|
|
4697
5004
|
const failures = results.filter((r) => !r.ok);
|
|
4698
|
-
if (failures.length === 0)
|
|
4699
|
-
else
|
|
5005
|
+
if (failures.length === 0) print.line(" All checks passed.\n");
|
|
5006
|
+
else print.line(` ${failures.length} issue(s) found.\n`);
|
|
4700
5007
|
blank();
|
|
4701
5008
|
}
|
|
4702
5009
|
//#endregion
|
|
@@ -4782,7 +5089,7 @@ function sleepSync(ms) {
|
|
|
4782
5089
|
}
|
|
4783
5090
|
const LAUNCHD_LABEL = "dev.first-tree-hub.client";
|
|
4784
5091
|
const SYSTEMD_UNIT = "first-tree-hub-client.service";
|
|
4785
|
-
const LOG_DIR = join(DEFAULT_HOME_DIR$1, "logs");
|
|
5092
|
+
const LOG_DIR$1 = join(DEFAULT_HOME_DIR$1, "logs");
|
|
4786
5093
|
function whichBin(name) {
|
|
4787
5094
|
try {
|
|
4788
5095
|
return execFileSync(process.platform === "win32" ? "where" : "which", [name], {
|
|
@@ -4824,7 +5131,7 @@ function resolveCliInvocation() {
|
|
|
4824
5131
|
};
|
|
4825
5132
|
}
|
|
4826
5133
|
function ensureLogDir() {
|
|
4827
|
-
mkdirSync(LOG_DIR, {
|
|
5134
|
+
mkdirSync(LOG_DIR$1, {
|
|
4828
5135
|
recursive: true,
|
|
4829
5136
|
mode: 448
|
|
4830
5137
|
});
|
|
@@ -4845,8 +5152,8 @@ function renderPlist(invocation) {
|
|
|
4845
5152
|
"start",
|
|
4846
5153
|
"--no-interactive"
|
|
4847
5154
|
]).map((a) => ` <string>${escapeXml(a)}</string>`).join("\n");
|
|
4848
|
-
const
|
|
4849
|
-
const
|
|
5155
|
+
const stdoutFallback = join(LOG_DIR$1, "client.stdout.log");
|
|
5156
|
+
const stderrFallback = join(LOG_DIR$1, "client.stderr.log");
|
|
4850
5157
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
4851
5158
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTD/PropertyList-1.0.dtd">
|
|
4852
5159
|
<plist version="1.0">
|
|
@@ -4861,6 +5168,8 @@ ${argsXml}
|
|
|
4861
5168
|
<dict>
|
|
4862
5169
|
<key>PATH</key>
|
|
4863
5170
|
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
5171
|
+
<key>FIRST_TREE_HUB_SERVICE_MODE</key>
|
|
5172
|
+
<string>1</string>
|
|
4864
5173
|
</dict>
|
|
4865
5174
|
<key>RunAtLoad</key>
|
|
4866
5175
|
<true/>
|
|
@@ -4872,9 +5181,9 @@ ${argsXml}
|
|
|
4872
5181
|
<key>ThrottleInterval</key>
|
|
4873
5182
|
<integer>10</integer>
|
|
4874
5183
|
<key>StandardOutPath</key>
|
|
4875
|
-
<string>${escapeXml(
|
|
5184
|
+
<string>${escapeXml(stdoutFallback)}</string>
|
|
4876
5185
|
<key>StandardErrorPath</key>
|
|
4877
|
-
<string>${escapeXml(
|
|
5186
|
+
<string>${escapeXml(stderrFallback)}</string>
|
|
4878
5187
|
</dict>
|
|
4879
5188
|
</plist>
|
|
4880
5189
|
`;
|
|
@@ -4947,7 +5256,7 @@ function installLaunchd() {
|
|
|
4947
5256
|
const target = launchctlDomainTarget();
|
|
4948
5257
|
const bootoutRes = runCapture("launchctl", ["bootout", `${target}/${LAUNCHD_LABEL}`], 15e3);
|
|
4949
5258
|
if (!bootoutRes.ok) {
|
|
4950
|
-
if (!/not find|no such|not loaded/i.test(bootoutRes.stderr))
|
|
5259
|
+
if (!/not find|no such|not loaded/i.test(bootoutRes.stderr)) print.line(` warning: launchctl bootout: ${bootoutRes.stderr || `exit ${bootoutRes.code ?? "unknown"}`}\n`);
|
|
4951
5260
|
}
|
|
4952
5261
|
waitForLabelEvicted(target, LAUNCHD_LABEL, 1e4);
|
|
4953
5262
|
let lastBootstrapErr = null;
|
|
@@ -4966,13 +5275,13 @@ function installLaunchd() {
|
|
|
4966
5275
|
}
|
|
4967
5276
|
if (lastBootstrapErr) throw new Error(`launchctl bootstrap failed: ${lastBootstrapErr.stderr || `exit ${lastBootstrapErr.code ?? "unknown"}`}\n Command: launchctl bootstrap ${target} ${plistPath}\n Recovery: \`launchctl bootout ${target}/${LAUNCHD_LABEL}\` then \`first-tree-hub service install\`.`);
|
|
4968
5277
|
const enableRes = runCapture("launchctl", ["enable", `${target}/${LAUNCHD_LABEL}`], 5e3);
|
|
4969
|
-
if (!enableRes.ok)
|
|
5278
|
+
if (!enableRes.ok) print.line(` warning: launchctl enable: ${enableRes.stderr || `exit ${enableRes.code ?? "unknown"}`}\n`);
|
|
4970
5279
|
const { state, detail } = launchdState();
|
|
4971
5280
|
return {
|
|
4972
5281
|
platform: "launchd",
|
|
4973
5282
|
label: LAUNCHD_LABEL,
|
|
4974
5283
|
unitPath: plistPath,
|
|
4975
|
-
logDir: LOG_DIR,
|
|
5284
|
+
logDir: LOG_DIR$1,
|
|
4976
5285
|
state,
|
|
4977
5286
|
detail
|
|
4978
5287
|
};
|
|
@@ -4980,13 +5289,13 @@ function installLaunchd() {
|
|
|
4980
5289
|
function uninstallLaunchd() {
|
|
4981
5290
|
const plistPath = launchdPlistPath();
|
|
4982
5291
|
const res = runCapture("launchctl", ["bootout", `${launchctlDomainTarget()}/${LAUNCHD_LABEL}`], 15e3);
|
|
4983
|
-
if (!res.ok && !/not find|no such|not loaded/i.test(res.stderr))
|
|
5292
|
+
if (!res.ok && !/not find|no such|not loaded/i.test(res.stderr)) print.line(` warning: bootout during uninstall: ${res.stderr || `exit ${res.code ?? "unknown"}`}\n`);
|
|
4984
5293
|
if (existsSync(plistPath)) rmSync(plistPath);
|
|
4985
5294
|
return {
|
|
4986
5295
|
platform: "launchd",
|
|
4987
5296
|
label: LAUNCHD_LABEL,
|
|
4988
5297
|
unitPath: plistPath,
|
|
4989
|
-
logDir: LOG_DIR,
|
|
5298
|
+
logDir: LOG_DIR$1,
|
|
4990
5299
|
state: "not-installed"
|
|
4991
5300
|
};
|
|
4992
5301
|
}
|
|
@@ -5004,9 +5313,10 @@ Type=simple
|
|
|
5004
5313
|
ExecStart=${invocation.kind === "bin" ? `${shellQuote(invocation.program)} client start --no-interactive` : `${shellQuote(invocation.program)} ${invocation.args.map(shellQuote).join(" ")} client start --no-interactive`}
|
|
5005
5314
|
Restart=always
|
|
5006
5315
|
RestartSec=10
|
|
5007
|
-
StandardOutput=append:${join(LOG_DIR, "client.
|
|
5008
|
-
StandardError=append:${join(LOG_DIR, "client.
|
|
5316
|
+
StandardOutput=append:${join(LOG_DIR$1, "client.stdout.log")}
|
|
5317
|
+
StandardError=append:${join(LOG_DIR$1, "client.stderr.log")}
|
|
5009
5318
|
Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
5319
|
+
Environment=FIRST_TREE_HUB_SERVICE_MODE=1
|
|
5010
5320
|
|
|
5011
5321
|
[Install]
|
|
5012
5322
|
WantedBy=default.target
|
|
@@ -5061,7 +5371,7 @@ function installSystemd() {
|
|
|
5061
5371
|
platform: "systemd",
|
|
5062
5372
|
label: SYSTEMD_UNIT,
|
|
5063
5373
|
unitPath,
|
|
5064
|
-
logDir: LOG_DIR,
|
|
5374
|
+
logDir: LOG_DIR$1,
|
|
5065
5375
|
state,
|
|
5066
5376
|
detail
|
|
5067
5377
|
};
|
|
@@ -5074,15 +5384,15 @@ function uninstallSystemd() {
|
|
|
5074
5384
|
"--now",
|
|
5075
5385
|
SYSTEMD_UNIT
|
|
5076
5386
|
], 1e4);
|
|
5077
|
-
if (!disableRes.ok && !/not found|no such|not loaded/i.test(disableRes.stderr))
|
|
5387
|
+
if (!disableRes.ok && !/not found|no such|not loaded/i.test(disableRes.stderr)) print.line(` warning: systemctl disable during uninstall: ${disableRes.stderr || `exit ${disableRes.code ?? "unknown"}`}\n`);
|
|
5078
5388
|
if (existsSync(unitPath)) rmSync(unitPath);
|
|
5079
5389
|
const reloadRes = runCapture("systemctl", ["--user", "daemon-reload"], 5e3);
|
|
5080
|
-
if (!reloadRes.ok)
|
|
5390
|
+
if (!reloadRes.ok) print.line(` warning: systemctl daemon-reload during uninstall: ${reloadRes.stderr || `exit ${reloadRes.code ?? "unknown"}`}\n`);
|
|
5081
5391
|
return {
|
|
5082
5392
|
platform: "systemd",
|
|
5083
5393
|
label: SYSTEMD_UNIT,
|
|
5084
5394
|
unitPath,
|
|
5085
|
-
logDir: LOG_DIR,
|
|
5395
|
+
logDir: LOG_DIR$1,
|
|
5086
5396
|
state: "not-installed"
|
|
5087
5397
|
};
|
|
5088
5398
|
}
|
|
@@ -5108,7 +5418,7 @@ function getClientServiceStatus() {
|
|
|
5108
5418
|
platform: "launchd",
|
|
5109
5419
|
label: LAUNCHD_LABEL,
|
|
5110
5420
|
unitPath: launchdPlistPath(),
|
|
5111
|
-
logDir: LOG_DIR,
|
|
5421
|
+
logDir: LOG_DIR$1,
|
|
5112
5422
|
state,
|
|
5113
5423
|
detail
|
|
5114
5424
|
};
|
|
@@ -5119,7 +5429,7 @@ function getClientServiceStatus() {
|
|
|
5119
5429
|
platform: "systemd",
|
|
5120
5430
|
label: SYSTEMD_UNIT,
|
|
5121
5431
|
unitPath: systemdUnitPath(),
|
|
5122
|
-
logDir: LOG_DIR,
|
|
5432
|
+
logDir: LOG_DIR$1,
|
|
5123
5433
|
state,
|
|
5124
5434
|
detail
|
|
5125
5435
|
};
|
|
@@ -5128,7 +5438,7 @@ function getClientServiceStatus() {
|
|
|
5128
5438
|
platform: "unsupported",
|
|
5129
5439
|
label: "",
|
|
5130
5440
|
unitPath: "",
|
|
5131
|
-
logDir: LOG_DIR,
|
|
5441
|
+
logDir: LOG_DIR$1,
|
|
5132
5442
|
state: "not-installed",
|
|
5133
5443
|
detail: `platform ${process.platform} not supported`
|
|
5134
5444
|
};
|
|
@@ -5168,22 +5478,22 @@ function runHomeMigration() {
|
|
|
5168
5478
|
envOverride: process.env.FIRST_TREE_HUB_HOME ?? null
|
|
5169
5479
|
});
|
|
5170
5480
|
if (!result.migrated) {
|
|
5171
|
-
if (result.reason === "failed")
|
|
5481
|
+
if (result.reason === "failed") print.line(`[first-tree-hub] WARNING: failed to auto-migrate legacy home ${result.from} → ${result.to}: ${result.error ?? "unknown error"}\n Resolve manually: cp -R "${result.from}" "${result.to}"\n`);
|
|
5172
5482
|
return;
|
|
5173
5483
|
}
|
|
5174
|
-
|
|
5484
|
+
print.line(`[first-tree-hub] Copied client home to new layout: ${result.from} → ${result.to}\n (Legacy directory preserved as a backup — delete it manually once you've verified the new location works.)\n`);
|
|
5175
5485
|
if (process.argv.includes("--no-interactive")) {
|
|
5176
|
-
|
|
5486
|
+
print.line("[first-tree-hub] Note: running as background service — skipped auto re-register to avoid self-termination.\n Run `first-tree-hub client service install` from a terminal to refresh log paths.\n");
|
|
5177
5487
|
return;
|
|
5178
5488
|
}
|
|
5179
5489
|
const status = getClientServiceStatus();
|
|
5180
5490
|
if (status.platform === "unsupported" || status.state === "not-installed") return;
|
|
5181
5491
|
try {
|
|
5182
5492
|
installClientService();
|
|
5183
|
-
|
|
5493
|
+
print.line(`[first-tree-hub] Re-registered background service with new home paths.\n`);
|
|
5184
5494
|
} catch (err) {
|
|
5185
5495
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5186
|
-
|
|
5496
|
+
print.line(`[first-tree-hub] WARNING: home migration succeeded but re-registering the background service failed: ${msg}\n Run \`first-tree-hub client service install\` to refresh log paths.\n`);
|
|
5187
5497
|
}
|
|
5188
5498
|
}
|
|
5189
5499
|
//#endregion
|
|
@@ -5319,7 +5629,7 @@ async function onboardCreate(args) {
|
|
|
5319
5629
|
const metadata = {};
|
|
5320
5630
|
if (args.role) metadata.role = args.role;
|
|
5321
5631
|
if (args.domains) metadata.domains = args.domains.split(",").map((d) => d.trim());
|
|
5322
|
-
|
|
5632
|
+
print.line(`Creating agent "${args.id}"...\n`);
|
|
5323
5633
|
const primary = await createAgentViaAdmin(serverUrl, accessToken, {
|
|
5324
5634
|
name: args.id,
|
|
5325
5635
|
type: args.type,
|
|
@@ -5328,11 +5638,11 @@ async function onboardCreate(args) {
|
|
|
5328
5638
|
metadata: Object.keys(metadata).length > 0 ? metadata : void 0,
|
|
5329
5639
|
clientId: args.type === "human" ? void 0 : args.clientId
|
|
5330
5640
|
});
|
|
5331
|
-
|
|
5641
|
+
print.line(`Agent "${args.id}" created (uuid ${primary.uuid}).\n`);
|
|
5332
5642
|
if (args.type !== "human") saveAgentConfig(args.id, primary.uuid, "claude-code");
|
|
5333
5643
|
let assistantUuid = null;
|
|
5334
5644
|
if (args.assistant) {
|
|
5335
|
-
|
|
5645
|
+
print.line(`Creating assistant "${args.assistant}"...\n`);
|
|
5336
5646
|
try {
|
|
5337
5647
|
const assistant = await createAgentViaAdmin(serverUrl, accessToken, {
|
|
5338
5648
|
name: args.assistant,
|
|
@@ -5346,21 +5656,21 @@ async function onboardCreate(args) {
|
|
|
5346
5656
|
});
|
|
5347
5657
|
assistantUuid = assistant.uuid;
|
|
5348
5658
|
saveAgentConfig(args.assistant, assistant.uuid, "claude-code");
|
|
5349
|
-
|
|
5659
|
+
print.line(`Assistant "${args.assistant}" ready.\n`);
|
|
5350
5660
|
} catch (err) {
|
|
5351
5661
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5352
|
-
|
|
5662
|
+
print.line(`Warning: Failed to create assistant "${args.assistant}": ${msg}\n`);
|
|
5353
5663
|
}
|
|
5354
5664
|
}
|
|
5355
5665
|
const runtimeAgent = args.type === "human" ? args.assistant : args.id;
|
|
5356
5666
|
if (args.feishuBotAppId && args.feishuBotAppSecret) {
|
|
5357
5667
|
const { bindFeishuBot } = await import("./feishu-GlaczcVf.mjs").then((n) => n.r);
|
|
5358
5668
|
const targetAgentUuid = args.type === "human" ? assistantUuid : primary.uuid;
|
|
5359
|
-
if (!targetAgentUuid)
|
|
5669
|
+
if (!targetAgentUuid) print.line(`Warning: Cannot bind Feishu bot — no runtime agent available for "${args.id}".\n`);
|
|
5360
5670
|
else {
|
|
5361
|
-
|
|
5671
|
+
print.line("Binding Feishu bot...\n");
|
|
5362
5672
|
await bindFeishuBot(serverUrl, accessToken, targetAgentUuid, args.feishuBotAppId, args.feishuBotAppSecret);
|
|
5363
|
-
|
|
5673
|
+
print.line("Feishu bot bound.\n");
|
|
5364
5674
|
}
|
|
5365
5675
|
}
|
|
5366
5676
|
setConfigValue(join(DEFAULT_CONFIG_DIR, "client.yaml"), "server.url", serverUrl);
|
|
@@ -5369,21 +5679,21 @@ async function onboardCreate(args) {
|
|
|
5369
5679
|
unlinkSync(STATE_FILE);
|
|
5370
5680
|
} catch {}
|
|
5371
5681
|
const typeLabel = args.type === "human" ? "Human" : args.type === "autonomous_agent" ? "Agent" : "Assistant";
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
if (args.assistant)
|
|
5375
|
-
if (runtimeAgent)
|
|
5376
|
-
if (args.feishuBotAppId)
|
|
5682
|
+
print.line("\n✅ Onboard complete!\n\n");
|
|
5683
|
+
print.line(` ${typeLabel}:${" ".repeat(Math.max(1, 10 - typeLabel.length))}${args.id}\n`);
|
|
5684
|
+
if (args.assistant) print.line(` Assistant: ${args.assistant}\n`);
|
|
5685
|
+
if (runtimeAgent) print.line(` Config: ${DEFAULT_HOME_DIR$1}/config/agents/${runtimeAgent}/agent.yaml\n`);
|
|
5686
|
+
if (args.feishuBotAppId) print.line(` Feishu: bot bound (${args.feishuBotAppId})\n`);
|
|
5377
5687
|
if (args.type === "human") {
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
if (!args.feishuBotAppId)
|
|
5688
|
+
print.line("\n Next step — bind your Feishu account:\n");
|
|
5689
|
+
print.line(` Send this message to the bot in Feishu: /bind ${args.id}\n`);
|
|
5690
|
+
if (!args.feishuBotAppId) print.line(" (requires a Feishu bot to be configured in the system)\n");
|
|
5381
5691
|
}
|
|
5382
5692
|
if (runtimeAgent) {
|
|
5383
|
-
|
|
5384
|
-
|
|
5693
|
+
print.line("\n Start the agent:\n");
|
|
5694
|
+
print.line(" first-tree-hub client start\n");
|
|
5385
5695
|
}
|
|
5386
|
-
|
|
5696
|
+
print.line("\n");
|
|
5387
5697
|
}
|
|
5388
5698
|
//#endregion
|
|
5389
5699
|
//#region src/core/prompt.ts
|
|
@@ -5495,2713 +5805,7 @@ function setNestedByDot(obj, dotPath, value) {
|
|
|
5495
5805
|
if (lastKey !== void 0) current[lastKey] = value;
|
|
5496
5806
|
}
|
|
5497
5807
|
//#endregion
|
|
5498
|
-
//#region
|
|
5499
|
-
var require_sbmh = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5500
|
-
/**
|
|
5501
|
-
* Copyright Brian White. All rights reserved.
|
|
5502
|
-
*
|
|
5503
|
-
* @see https://github.com/mscdex/streamsearch
|
|
5504
|
-
*
|
|
5505
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5506
|
-
* of this software and associated documentation files (the "Software"), to
|
|
5507
|
-
* deal in the Software without restriction, including without limitation the
|
|
5508
|
-
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
5509
|
-
* sell copies of the Software, and to permit persons to whom the Software is
|
|
5510
|
-
* furnished to do so, subject to the following conditions:
|
|
5511
|
-
*
|
|
5512
|
-
* The above copyright notice and this permission notice shall be included in
|
|
5513
|
-
* all copies or substantial portions of the Software.
|
|
5514
|
-
*
|
|
5515
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
5516
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
5517
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
5518
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
5519
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
5520
|
-
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
5521
|
-
* IN THE SOFTWARE.
|
|
5522
|
-
*
|
|
5523
|
-
* Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation
|
|
5524
|
-
* by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool
|
|
5525
|
-
*/
|
|
5526
|
-
const { EventEmitter: EventEmitter$2 } = __require("node:events");
|
|
5527
|
-
const { inherits: inherits$5 } = __require("node:util");
|
|
5528
|
-
function SBMH(needle) {
|
|
5529
|
-
if (typeof needle === "string") needle = Buffer.from(needle);
|
|
5530
|
-
if (!Buffer.isBuffer(needle)) throw new TypeError("The needle has to be a String or a Buffer.");
|
|
5531
|
-
const needleLength = needle.length;
|
|
5532
|
-
const needleLastCharIndex = needleLength - 1;
|
|
5533
|
-
if (needleLength === 0) throw new Error("The needle cannot be an empty String/Buffer.");
|
|
5534
|
-
if (needleLength > 256) throw new Error("The needle cannot have a length bigger than 256.");
|
|
5535
|
-
this.maxMatches = Infinity;
|
|
5536
|
-
this.matches = 0;
|
|
5537
|
-
this._occ = new Uint8Array(256).fill(needleLength);
|
|
5538
|
-
this._lookbehind_size = 0;
|
|
5539
|
-
this._needle = needle;
|
|
5540
|
-
this._bufpos = 0;
|
|
5541
|
-
this._lookbehind = Buffer.alloc(needleLastCharIndex);
|
|
5542
|
-
for (var i = 0; i < needleLastCharIndex; ++i) this._occ[needle[i]] = needleLastCharIndex - i;
|
|
5543
|
-
}
|
|
5544
|
-
inherits$5(SBMH, EventEmitter$2);
|
|
5545
|
-
SBMH.prototype.reset = function() {
|
|
5546
|
-
this._lookbehind_size = 0;
|
|
5547
|
-
this.matches = 0;
|
|
5548
|
-
this._bufpos = 0;
|
|
5549
|
-
};
|
|
5550
|
-
SBMH.prototype.push = function(chunk, pos) {
|
|
5551
|
-
if (!Buffer.isBuffer(chunk)) chunk = Buffer.from(chunk, "binary");
|
|
5552
|
-
const chlen = chunk.length;
|
|
5553
|
-
this._bufpos = pos || 0;
|
|
5554
|
-
let r;
|
|
5555
|
-
while (r !== chlen && this.matches < this.maxMatches) r = this._sbmh_feed(chunk);
|
|
5556
|
-
return r;
|
|
5557
|
-
};
|
|
5558
|
-
SBMH.prototype._sbmh_feed = function(data) {
|
|
5559
|
-
const len = data.length;
|
|
5560
|
-
const needle = this._needle;
|
|
5561
|
-
const needleLength = needle.length;
|
|
5562
|
-
const needleLastCharIndex = needleLength - 1;
|
|
5563
|
-
const needleLastChar = needle[needleLastCharIndex];
|
|
5564
|
-
let pos = -this._lookbehind_size;
|
|
5565
|
-
let ch;
|
|
5566
|
-
if (pos < 0) {
|
|
5567
|
-
while (pos < 0 && pos <= len - needleLength) {
|
|
5568
|
-
ch = data[pos + needleLastCharIndex];
|
|
5569
|
-
if (ch === needleLastChar && this._sbmh_memcmp(data, pos, needleLastCharIndex)) {
|
|
5570
|
-
this._lookbehind_size = 0;
|
|
5571
|
-
++this.matches;
|
|
5572
|
-
this.emit("info", true);
|
|
5573
|
-
return this._bufpos = pos + needleLength;
|
|
5574
|
-
}
|
|
5575
|
-
pos += this._occ[ch];
|
|
5576
|
-
}
|
|
5577
|
-
while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) ++pos;
|
|
5578
|
-
if (pos >= 0) {
|
|
5579
|
-
this.emit("info", false, this._lookbehind, 0, this._lookbehind_size);
|
|
5580
|
-
this._lookbehind_size = 0;
|
|
5581
|
-
} else {
|
|
5582
|
-
const bytesToCutOff = this._lookbehind_size + pos;
|
|
5583
|
-
if (bytesToCutOff > 0) this.emit("info", false, this._lookbehind, 0, bytesToCutOff);
|
|
5584
|
-
this._lookbehind_size -= bytesToCutOff;
|
|
5585
|
-
this._lookbehind.copy(this._lookbehind, 0, bytesToCutOff, this._lookbehind_size);
|
|
5586
|
-
data.copy(this._lookbehind, this._lookbehind_size);
|
|
5587
|
-
this._lookbehind_size += len;
|
|
5588
|
-
this._bufpos = len;
|
|
5589
|
-
return len;
|
|
5590
|
-
}
|
|
5591
|
-
}
|
|
5592
|
-
pos = data.indexOf(needle, pos + this._bufpos);
|
|
5593
|
-
if (pos !== -1) {
|
|
5594
|
-
++this.matches;
|
|
5595
|
-
if (pos === 0) this.emit("info", true);
|
|
5596
|
-
else this.emit("info", true, data, this._bufpos, pos);
|
|
5597
|
-
return this._bufpos = pos + needleLength;
|
|
5598
|
-
}
|
|
5599
|
-
pos = len - needleLastCharIndex;
|
|
5600
|
-
if (pos < 0) pos = 0;
|
|
5601
|
-
while (pos !== len && (data[pos] !== needle[0] || Buffer.compare(data.subarray(pos + 1, len), needle.subarray(1, len - pos)) !== 0)) ++pos;
|
|
5602
|
-
if (pos !== len) {
|
|
5603
|
-
data.copy(this._lookbehind, 0, pos, len);
|
|
5604
|
-
this._lookbehind_size = len - pos;
|
|
5605
|
-
}
|
|
5606
|
-
if (pos !== 0) this.emit("info", false, data, this._bufpos, pos);
|
|
5607
|
-
this._bufpos = len;
|
|
5608
|
-
return len;
|
|
5609
|
-
};
|
|
5610
|
-
SBMH.prototype._sbmh_lookup_char = function(data, pos) {
|
|
5611
|
-
return pos < 0 ? this._lookbehind[this._lookbehind_size + pos] : data[pos];
|
|
5612
|
-
};
|
|
5613
|
-
SBMH.prototype._sbmh_memcmp = function(data, pos, len) {
|
|
5614
|
-
for (var i = 0; i < len; ++i) if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) return false;
|
|
5615
|
-
return true;
|
|
5616
|
-
};
|
|
5617
|
-
module.exports = SBMH;
|
|
5618
|
-
}));
|
|
5619
|
-
//#endregion
|
|
5620
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js
|
|
5621
|
-
var require_PartStream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5622
|
-
const inherits$4 = __require("node:util").inherits;
|
|
5623
|
-
const ReadableStream = __require("node:stream").Readable;
|
|
5624
|
-
function PartStream(opts) {
|
|
5625
|
-
ReadableStream.call(this, opts);
|
|
5626
|
-
}
|
|
5627
|
-
inherits$4(PartStream, ReadableStream);
|
|
5628
|
-
PartStream.prototype._read = function(n) {};
|
|
5629
|
-
module.exports = PartStream;
|
|
5630
|
-
}));
|
|
5631
|
-
//#endregion
|
|
5632
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/getLimit.js
|
|
5633
|
-
var require_getLimit = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5634
|
-
module.exports = function getLimit(limits, name, defaultLimit) {
|
|
5635
|
-
if (!limits || limits[name] === void 0 || limits[name] === null) return defaultLimit;
|
|
5636
|
-
if (typeof limits[name] !== "number" || isNaN(limits[name])) throw new TypeError("Limit " + name + " is not a valid number");
|
|
5637
|
-
return limits[name];
|
|
5638
|
-
};
|
|
5639
|
-
}));
|
|
5640
|
-
//#endregion
|
|
5641
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js
|
|
5642
|
-
var require_HeaderParser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5643
|
-
const EventEmitter$1 = __require("node:events").EventEmitter;
|
|
5644
|
-
const inherits$3 = __require("node:util").inherits;
|
|
5645
|
-
const getLimit = require_getLimit();
|
|
5646
|
-
const StreamSearch = require_sbmh();
|
|
5647
|
-
const B_DCRLF = Buffer.from("\r\n\r\n");
|
|
5648
|
-
const RE_CRLF = /\r\n/g;
|
|
5649
|
-
const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/;
|
|
5650
|
-
function HeaderParser(cfg) {
|
|
5651
|
-
EventEmitter$1.call(this);
|
|
5652
|
-
cfg = cfg || {};
|
|
5653
|
-
const self = this;
|
|
5654
|
-
this.nread = 0;
|
|
5655
|
-
this.maxed = false;
|
|
5656
|
-
this.npairs = 0;
|
|
5657
|
-
this.maxHeaderPairs = getLimit(cfg, "maxHeaderPairs", 2e3);
|
|
5658
|
-
this.maxHeaderSize = getLimit(cfg, "maxHeaderSize", 80 * 1024);
|
|
5659
|
-
this.buffer = "";
|
|
5660
|
-
this.header = {};
|
|
5661
|
-
this.finished = false;
|
|
5662
|
-
this.ss = new StreamSearch(B_DCRLF);
|
|
5663
|
-
this.ss.on("info", function(isMatch, data, start, end) {
|
|
5664
|
-
if (data && !self.maxed) {
|
|
5665
|
-
if (self.nread + end - start >= self.maxHeaderSize) {
|
|
5666
|
-
end = self.maxHeaderSize - self.nread + start;
|
|
5667
|
-
self.nread = self.maxHeaderSize;
|
|
5668
|
-
self.maxed = true;
|
|
5669
|
-
} else self.nread += end - start;
|
|
5670
|
-
self.buffer += data.toString("binary", start, end);
|
|
5671
|
-
}
|
|
5672
|
-
if (isMatch) self._finish();
|
|
5673
|
-
});
|
|
5674
|
-
}
|
|
5675
|
-
inherits$3(HeaderParser, EventEmitter$1);
|
|
5676
|
-
HeaderParser.prototype.push = function(data) {
|
|
5677
|
-
const r = this.ss.push(data);
|
|
5678
|
-
if (this.finished) return r;
|
|
5679
|
-
};
|
|
5680
|
-
HeaderParser.prototype.reset = function() {
|
|
5681
|
-
this.finished = false;
|
|
5682
|
-
this.buffer = "";
|
|
5683
|
-
this.header = {};
|
|
5684
|
-
this.ss.reset();
|
|
5685
|
-
};
|
|
5686
|
-
HeaderParser.prototype._finish = function() {
|
|
5687
|
-
if (this.buffer) this._parseHeader();
|
|
5688
|
-
this.ss.matches = this.ss.maxMatches;
|
|
5689
|
-
const header = this.header;
|
|
5690
|
-
this.header = {};
|
|
5691
|
-
this.buffer = "";
|
|
5692
|
-
this.finished = true;
|
|
5693
|
-
this.nread = this.npairs = 0;
|
|
5694
|
-
this.maxed = false;
|
|
5695
|
-
this.emit("header", header);
|
|
5696
|
-
};
|
|
5697
|
-
HeaderParser.prototype._parseHeader = function() {
|
|
5698
|
-
if (this.npairs === this.maxHeaderPairs) return;
|
|
5699
|
-
const lines = this.buffer.split(RE_CRLF);
|
|
5700
|
-
const len = lines.length;
|
|
5701
|
-
let m, h;
|
|
5702
|
-
for (var i = 0; i < len; ++i) {
|
|
5703
|
-
if (lines[i].length === 0) continue;
|
|
5704
|
-
if (lines[i][0] === " " || lines[i][0] === " ") {
|
|
5705
|
-
if (h) {
|
|
5706
|
-
this.header[h][this.header[h].length - 1] += lines[i];
|
|
5707
|
-
continue;
|
|
5708
|
-
}
|
|
5709
|
-
}
|
|
5710
|
-
const posColon = lines[i].indexOf(":");
|
|
5711
|
-
if (posColon === -1 || posColon === 0) return;
|
|
5712
|
-
m = RE_HDR.exec(lines[i]);
|
|
5713
|
-
h = m[1].toLowerCase();
|
|
5714
|
-
this.header[h] = this.header[h] || [];
|
|
5715
|
-
this.header[h].push(m[2] || "");
|
|
5716
|
-
if (++this.npairs === this.maxHeaderPairs) break;
|
|
5717
|
-
}
|
|
5718
|
-
};
|
|
5719
|
-
module.exports = HeaderParser;
|
|
5720
|
-
}));
|
|
5721
|
-
//#endregion
|
|
5722
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js
|
|
5723
|
-
var require_Dicer = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5724
|
-
const WritableStream$1 = __require("node:stream").Writable;
|
|
5725
|
-
const inherits$2 = __require("node:util").inherits;
|
|
5726
|
-
const StreamSearch = require_sbmh();
|
|
5727
|
-
const PartStream = require_PartStream();
|
|
5728
|
-
const HeaderParser = require_HeaderParser();
|
|
5729
|
-
const DASH = 45;
|
|
5730
|
-
const B_ONEDASH = Buffer.from("-");
|
|
5731
|
-
const B_CRLF = Buffer.from("\r\n");
|
|
5732
|
-
const EMPTY_FN = function() {};
|
|
5733
|
-
function Dicer(cfg) {
|
|
5734
|
-
if (!(this instanceof Dicer)) return new Dicer(cfg);
|
|
5735
|
-
WritableStream$1.call(this, cfg);
|
|
5736
|
-
if (!cfg || !cfg.headerFirst && typeof cfg.boundary !== "string") throw new TypeError("Boundary required");
|
|
5737
|
-
if (typeof cfg.boundary === "string") this.setBoundary(cfg.boundary);
|
|
5738
|
-
else this._bparser = void 0;
|
|
5739
|
-
this._headerFirst = cfg.headerFirst;
|
|
5740
|
-
this._dashes = 0;
|
|
5741
|
-
this._parts = 0;
|
|
5742
|
-
this._finished = false;
|
|
5743
|
-
this._realFinish = false;
|
|
5744
|
-
this._isPreamble = true;
|
|
5745
|
-
this._justMatched = false;
|
|
5746
|
-
this._firstWrite = true;
|
|
5747
|
-
this._inHeader = true;
|
|
5748
|
-
this._part = void 0;
|
|
5749
|
-
this._cb = void 0;
|
|
5750
|
-
this._ignoreData = false;
|
|
5751
|
-
this._partOpts = { highWaterMark: cfg.partHwm };
|
|
5752
|
-
this._pause = false;
|
|
5753
|
-
const self = this;
|
|
5754
|
-
this._hparser = new HeaderParser(cfg);
|
|
5755
|
-
this._hparser.on("header", function(header) {
|
|
5756
|
-
self._inHeader = false;
|
|
5757
|
-
self._part.emit("header", header);
|
|
5758
|
-
});
|
|
5759
|
-
}
|
|
5760
|
-
inherits$2(Dicer, WritableStream$1);
|
|
5761
|
-
Dicer.prototype.emit = function(ev) {
|
|
5762
|
-
if (ev === "finish" && !this._realFinish) {
|
|
5763
|
-
if (!this._finished) {
|
|
5764
|
-
const self = this;
|
|
5765
|
-
process.nextTick(function() {
|
|
5766
|
-
self.emit("error", /* @__PURE__ */ new Error("Unexpected end of multipart data"));
|
|
5767
|
-
if (self._part && !self._ignoreData) {
|
|
5768
|
-
const type = self._isPreamble ? "Preamble" : "Part";
|
|
5769
|
-
self._part.emit("error", /* @__PURE__ */ new Error(type + " terminated early due to unexpected end of multipart data"));
|
|
5770
|
-
self._part.push(null);
|
|
5771
|
-
process.nextTick(function() {
|
|
5772
|
-
self._realFinish = true;
|
|
5773
|
-
self.emit("finish");
|
|
5774
|
-
self._realFinish = false;
|
|
5775
|
-
});
|
|
5776
|
-
return;
|
|
5777
|
-
}
|
|
5778
|
-
self._realFinish = true;
|
|
5779
|
-
self.emit("finish");
|
|
5780
|
-
self._realFinish = false;
|
|
5781
|
-
});
|
|
5782
|
-
}
|
|
5783
|
-
} else WritableStream$1.prototype.emit.apply(this, arguments);
|
|
5784
|
-
};
|
|
5785
|
-
Dicer.prototype._write = function(data, encoding, cb) {
|
|
5786
|
-
if (!this._hparser && !this._bparser) return cb();
|
|
5787
|
-
if (this._headerFirst && this._isPreamble) {
|
|
5788
|
-
if (!this._part) {
|
|
5789
|
-
this._part = new PartStream(this._partOpts);
|
|
5790
|
-
if (this.listenerCount("preamble") !== 0) this.emit("preamble", this._part);
|
|
5791
|
-
else this._ignore();
|
|
5792
|
-
}
|
|
5793
|
-
const r = this._hparser.push(data);
|
|
5794
|
-
if (!this._inHeader && r !== void 0 && r < data.length) data = data.slice(r);
|
|
5795
|
-
else return cb();
|
|
5796
|
-
}
|
|
5797
|
-
if (this._firstWrite) {
|
|
5798
|
-
this._bparser.push(B_CRLF);
|
|
5799
|
-
this._firstWrite = false;
|
|
5800
|
-
}
|
|
5801
|
-
this._bparser.push(data);
|
|
5802
|
-
if (this._pause) this._cb = cb;
|
|
5803
|
-
else cb();
|
|
5804
|
-
};
|
|
5805
|
-
Dicer.prototype.reset = function() {
|
|
5806
|
-
this._part = void 0;
|
|
5807
|
-
this._bparser = void 0;
|
|
5808
|
-
this._hparser = void 0;
|
|
5809
|
-
};
|
|
5810
|
-
Dicer.prototype.setBoundary = function(boundary) {
|
|
5811
|
-
const self = this;
|
|
5812
|
-
this._bparser = new StreamSearch("\r\n--" + boundary);
|
|
5813
|
-
this._bparser.on("info", function(isMatch, data, start, end) {
|
|
5814
|
-
self._oninfo(isMatch, data, start, end);
|
|
5815
|
-
});
|
|
5816
|
-
};
|
|
5817
|
-
Dicer.prototype._ignore = function() {
|
|
5818
|
-
if (this._part && !this._ignoreData) {
|
|
5819
|
-
this._ignoreData = true;
|
|
5820
|
-
this._part.on("error", EMPTY_FN);
|
|
5821
|
-
this._part.resume();
|
|
5822
|
-
}
|
|
5823
|
-
};
|
|
5824
|
-
Dicer.prototype._oninfo = function(isMatch, data, start, end) {
|
|
5825
|
-
let buf;
|
|
5826
|
-
const self = this;
|
|
5827
|
-
let i = 0;
|
|
5828
|
-
let r;
|
|
5829
|
-
let shouldWriteMore = true;
|
|
5830
|
-
if (!this._part && this._justMatched && data) {
|
|
5831
|
-
while (this._dashes < 2 && start + i < end) if (data[start + i] === DASH) {
|
|
5832
|
-
++i;
|
|
5833
|
-
++this._dashes;
|
|
5834
|
-
} else {
|
|
5835
|
-
if (this._dashes) buf = B_ONEDASH;
|
|
5836
|
-
this._dashes = 0;
|
|
5837
|
-
break;
|
|
5838
|
-
}
|
|
5839
|
-
if (this._dashes === 2) {
|
|
5840
|
-
if (start + i < end && this.listenerCount("trailer") !== 0) this.emit("trailer", data.slice(start + i, end));
|
|
5841
|
-
this.reset();
|
|
5842
|
-
this._finished = true;
|
|
5843
|
-
if (self._parts === 0) {
|
|
5844
|
-
self._realFinish = true;
|
|
5845
|
-
self.emit("finish");
|
|
5846
|
-
self._realFinish = false;
|
|
5847
|
-
}
|
|
5848
|
-
}
|
|
5849
|
-
if (this._dashes) return;
|
|
5850
|
-
}
|
|
5851
|
-
if (this._justMatched) this._justMatched = false;
|
|
5852
|
-
if (!this._part) {
|
|
5853
|
-
this._part = new PartStream(this._partOpts);
|
|
5854
|
-
this._part._read = function(n) {
|
|
5855
|
-
self._unpause();
|
|
5856
|
-
};
|
|
5857
|
-
if (this._isPreamble && this.listenerCount("preamble") !== 0) this.emit("preamble", this._part);
|
|
5858
|
-
else if (this._isPreamble !== true && this.listenerCount("part") !== 0) this.emit("part", this._part);
|
|
5859
|
-
else this._ignore();
|
|
5860
|
-
if (!this._isPreamble) this._inHeader = true;
|
|
5861
|
-
}
|
|
5862
|
-
if (data && start < end && !this._ignoreData) {
|
|
5863
|
-
if (this._isPreamble || !this._inHeader) {
|
|
5864
|
-
if (buf) shouldWriteMore = this._part.push(buf);
|
|
5865
|
-
shouldWriteMore = this._part.push(data.slice(start, end));
|
|
5866
|
-
if (!shouldWriteMore) this._pause = true;
|
|
5867
|
-
} else if (!this._isPreamble && this._inHeader) {
|
|
5868
|
-
if (buf) this._hparser.push(buf);
|
|
5869
|
-
r = this._hparser.push(data.slice(start, end));
|
|
5870
|
-
if (!this._inHeader && r !== void 0 && r < end) this._oninfo(false, data, start + r, end);
|
|
5871
|
-
}
|
|
5872
|
-
}
|
|
5873
|
-
if (isMatch) {
|
|
5874
|
-
this._hparser.reset();
|
|
5875
|
-
if (this._isPreamble) this._isPreamble = false;
|
|
5876
|
-
else if (start !== end) {
|
|
5877
|
-
++this._parts;
|
|
5878
|
-
this._part.on("end", function() {
|
|
5879
|
-
if (--self._parts === 0) if (self._finished) {
|
|
5880
|
-
self._realFinish = true;
|
|
5881
|
-
self.emit("finish");
|
|
5882
|
-
self._realFinish = false;
|
|
5883
|
-
} else self._unpause();
|
|
5884
|
-
});
|
|
5885
|
-
}
|
|
5886
|
-
this._part.push(null);
|
|
5887
|
-
this._part = void 0;
|
|
5888
|
-
this._ignoreData = false;
|
|
5889
|
-
this._justMatched = true;
|
|
5890
|
-
this._dashes = 0;
|
|
5891
|
-
}
|
|
5892
|
-
};
|
|
5893
|
-
Dicer.prototype._unpause = function() {
|
|
5894
|
-
if (!this._pause) return;
|
|
5895
|
-
this._pause = false;
|
|
5896
|
-
if (this._cb) {
|
|
5897
|
-
const cb = this._cb;
|
|
5898
|
-
this._cb = void 0;
|
|
5899
|
-
cb();
|
|
5900
|
-
}
|
|
5901
|
-
};
|
|
5902
|
-
module.exports = Dicer;
|
|
5903
|
-
}));
|
|
5904
|
-
//#endregion
|
|
5905
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/decodeText.js
|
|
5906
|
-
var require_decodeText = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5907
|
-
const utf8Decoder = new TextDecoder("utf-8");
|
|
5908
|
-
const textDecoders = new Map([["utf-8", utf8Decoder], ["utf8", utf8Decoder]]);
|
|
5909
|
-
function getDecoder(charset) {
|
|
5910
|
-
let lc;
|
|
5911
|
-
while (true) switch (charset) {
|
|
5912
|
-
case "utf-8":
|
|
5913
|
-
case "utf8": return decoders.utf8;
|
|
5914
|
-
case "latin1":
|
|
5915
|
-
case "ascii":
|
|
5916
|
-
case "us-ascii":
|
|
5917
|
-
case "iso-8859-1":
|
|
5918
|
-
case "iso8859-1":
|
|
5919
|
-
case "iso88591":
|
|
5920
|
-
case "iso_8859-1":
|
|
5921
|
-
case "windows-1252":
|
|
5922
|
-
case "iso_8859-1:1987":
|
|
5923
|
-
case "cp1252":
|
|
5924
|
-
case "x-cp1252": return decoders.latin1;
|
|
5925
|
-
case "utf16le":
|
|
5926
|
-
case "utf-16le":
|
|
5927
|
-
case "ucs2":
|
|
5928
|
-
case "ucs-2": return decoders.utf16le;
|
|
5929
|
-
case "base64": return decoders.base64;
|
|
5930
|
-
default:
|
|
5931
|
-
if (lc === void 0) {
|
|
5932
|
-
lc = true;
|
|
5933
|
-
charset = charset.toLowerCase();
|
|
5934
|
-
continue;
|
|
5935
|
-
}
|
|
5936
|
-
return decoders.other.bind(charset);
|
|
5937
|
-
}
|
|
5938
|
-
}
|
|
5939
|
-
const decoders = {
|
|
5940
|
-
utf8: (data, sourceEncoding) => {
|
|
5941
|
-
if (data.length === 0) return "";
|
|
5942
|
-
if (typeof data === "string") data = Buffer.from(data, sourceEncoding);
|
|
5943
|
-
return data.utf8Slice(0, data.length);
|
|
5944
|
-
},
|
|
5945
|
-
latin1: (data, sourceEncoding) => {
|
|
5946
|
-
if (data.length === 0) return "";
|
|
5947
|
-
if (typeof data === "string") return data;
|
|
5948
|
-
return data.latin1Slice(0, data.length);
|
|
5949
|
-
},
|
|
5950
|
-
utf16le: (data, sourceEncoding) => {
|
|
5951
|
-
if (data.length === 0) return "";
|
|
5952
|
-
if (typeof data === "string") data = Buffer.from(data, sourceEncoding);
|
|
5953
|
-
return data.ucs2Slice(0, data.length);
|
|
5954
|
-
},
|
|
5955
|
-
base64: (data, sourceEncoding) => {
|
|
5956
|
-
if (data.length === 0) return "";
|
|
5957
|
-
if (typeof data === "string") data = Buffer.from(data, sourceEncoding);
|
|
5958
|
-
return data.base64Slice(0, data.length);
|
|
5959
|
-
},
|
|
5960
|
-
other: (data, sourceEncoding) => {
|
|
5961
|
-
if (data.length === 0) return "";
|
|
5962
|
-
if (typeof data === "string") data = Buffer.from(data, sourceEncoding);
|
|
5963
|
-
if (textDecoders.has(exports.toString())) try {
|
|
5964
|
-
return textDecoders.get(exports).decode(data);
|
|
5965
|
-
} catch {}
|
|
5966
|
-
return typeof data === "string" ? data : data.toString();
|
|
5967
|
-
}
|
|
5968
|
-
};
|
|
5969
|
-
function decodeText(text, sourceEncoding, destEncoding) {
|
|
5970
|
-
if (text) return getDecoder(destEncoding)(text, sourceEncoding);
|
|
5971
|
-
return text;
|
|
5972
|
-
}
|
|
5973
|
-
module.exports = decodeText;
|
|
5974
|
-
}));
|
|
5975
|
-
//#endregion
|
|
5976
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/parseParams.js
|
|
5977
|
-
var require_parseParams = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5978
|
-
const decodeText = require_decodeText();
|
|
5979
|
-
const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g;
|
|
5980
|
-
const EncodedLookup = {
|
|
5981
|
-
"%00": "\0",
|
|
5982
|
-
"%01": "",
|
|
5983
|
-
"%02": "",
|
|
5984
|
-
"%03": "",
|
|
5985
|
-
"%04": "",
|
|
5986
|
-
"%05": "",
|
|
5987
|
-
"%06": "",
|
|
5988
|
-
"%07": "\x07",
|
|
5989
|
-
"%08": "\b",
|
|
5990
|
-
"%09": " ",
|
|
5991
|
-
"%0a": "\n",
|
|
5992
|
-
"%0A": "\n",
|
|
5993
|
-
"%0b": "\v",
|
|
5994
|
-
"%0B": "\v",
|
|
5995
|
-
"%0c": "\f",
|
|
5996
|
-
"%0C": "\f",
|
|
5997
|
-
"%0d": "\r",
|
|
5998
|
-
"%0D": "\r",
|
|
5999
|
-
"%0e": "",
|
|
6000
|
-
"%0E": "",
|
|
6001
|
-
"%0f": "",
|
|
6002
|
-
"%0F": "",
|
|
6003
|
-
"%10": "",
|
|
6004
|
-
"%11": "",
|
|
6005
|
-
"%12": "",
|
|
6006
|
-
"%13": "",
|
|
6007
|
-
"%14": "",
|
|
6008
|
-
"%15": "",
|
|
6009
|
-
"%16": "",
|
|
6010
|
-
"%17": "",
|
|
6011
|
-
"%18": "",
|
|
6012
|
-
"%19": "",
|
|
6013
|
-
"%1a": "",
|
|
6014
|
-
"%1A": "",
|
|
6015
|
-
"%1b": "\x1B",
|
|
6016
|
-
"%1B": "\x1B",
|
|
6017
|
-
"%1c": "",
|
|
6018
|
-
"%1C": "",
|
|
6019
|
-
"%1d": "",
|
|
6020
|
-
"%1D": "",
|
|
6021
|
-
"%1e": "",
|
|
6022
|
-
"%1E": "",
|
|
6023
|
-
"%1f": "",
|
|
6024
|
-
"%1F": "",
|
|
6025
|
-
"%20": " ",
|
|
6026
|
-
"%21": "!",
|
|
6027
|
-
"%22": "\"",
|
|
6028
|
-
"%23": "#",
|
|
6029
|
-
"%24": "$",
|
|
6030
|
-
"%25": "%",
|
|
6031
|
-
"%26": "&",
|
|
6032
|
-
"%27": "'",
|
|
6033
|
-
"%28": "(",
|
|
6034
|
-
"%29": ")",
|
|
6035
|
-
"%2a": "*",
|
|
6036
|
-
"%2A": "*",
|
|
6037
|
-
"%2b": "+",
|
|
6038
|
-
"%2B": "+",
|
|
6039
|
-
"%2c": ",",
|
|
6040
|
-
"%2C": ",",
|
|
6041
|
-
"%2d": "-",
|
|
6042
|
-
"%2D": "-",
|
|
6043
|
-
"%2e": ".",
|
|
6044
|
-
"%2E": ".",
|
|
6045
|
-
"%2f": "/",
|
|
6046
|
-
"%2F": "/",
|
|
6047
|
-
"%30": "0",
|
|
6048
|
-
"%31": "1",
|
|
6049
|
-
"%32": "2",
|
|
6050
|
-
"%33": "3",
|
|
6051
|
-
"%34": "4",
|
|
6052
|
-
"%35": "5",
|
|
6053
|
-
"%36": "6",
|
|
6054
|
-
"%37": "7",
|
|
6055
|
-
"%38": "8",
|
|
6056
|
-
"%39": "9",
|
|
6057
|
-
"%3a": ":",
|
|
6058
|
-
"%3A": ":",
|
|
6059
|
-
"%3b": ";",
|
|
6060
|
-
"%3B": ";",
|
|
6061
|
-
"%3c": "<",
|
|
6062
|
-
"%3C": "<",
|
|
6063
|
-
"%3d": "=",
|
|
6064
|
-
"%3D": "=",
|
|
6065
|
-
"%3e": ">",
|
|
6066
|
-
"%3E": ">",
|
|
6067
|
-
"%3f": "?",
|
|
6068
|
-
"%3F": "?",
|
|
6069
|
-
"%40": "@",
|
|
6070
|
-
"%41": "A",
|
|
6071
|
-
"%42": "B",
|
|
6072
|
-
"%43": "C",
|
|
6073
|
-
"%44": "D",
|
|
6074
|
-
"%45": "E",
|
|
6075
|
-
"%46": "F",
|
|
6076
|
-
"%47": "G",
|
|
6077
|
-
"%48": "H",
|
|
6078
|
-
"%49": "I",
|
|
6079
|
-
"%4a": "J",
|
|
6080
|
-
"%4A": "J",
|
|
6081
|
-
"%4b": "K",
|
|
6082
|
-
"%4B": "K",
|
|
6083
|
-
"%4c": "L",
|
|
6084
|
-
"%4C": "L",
|
|
6085
|
-
"%4d": "M",
|
|
6086
|
-
"%4D": "M",
|
|
6087
|
-
"%4e": "N",
|
|
6088
|
-
"%4E": "N",
|
|
6089
|
-
"%4f": "O",
|
|
6090
|
-
"%4F": "O",
|
|
6091
|
-
"%50": "P",
|
|
6092
|
-
"%51": "Q",
|
|
6093
|
-
"%52": "R",
|
|
6094
|
-
"%53": "S",
|
|
6095
|
-
"%54": "T",
|
|
6096
|
-
"%55": "U",
|
|
6097
|
-
"%56": "V",
|
|
6098
|
-
"%57": "W",
|
|
6099
|
-
"%58": "X",
|
|
6100
|
-
"%59": "Y",
|
|
6101
|
-
"%5a": "Z",
|
|
6102
|
-
"%5A": "Z",
|
|
6103
|
-
"%5b": "[",
|
|
6104
|
-
"%5B": "[",
|
|
6105
|
-
"%5c": "\\",
|
|
6106
|
-
"%5C": "\\",
|
|
6107
|
-
"%5d": "]",
|
|
6108
|
-
"%5D": "]",
|
|
6109
|
-
"%5e": "^",
|
|
6110
|
-
"%5E": "^",
|
|
6111
|
-
"%5f": "_",
|
|
6112
|
-
"%5F": "_",
|
|
6113
|
-
"%60": "`",
|
|
6114
|
-
"%61": "a",
|
|
6115
|
-
"%62": "b",
|
|
6116
|
-
"%63": "c",
|
|
6117
|
-
"%64": "d",
|
|
6118
|
-
"%65": "e",
|
|
6119
|
-
"%66": "f",
|
|
6120
|
-
"%67": "g",
|
|
6121
|
-
"%68": "h",
|
|
6122
|
-
"%69": "i",
|
|
6123
|
-
"%6a": "j",
|
|
6124
|
-
"%6A": "j",
|
|
6125
|
-
"%6b": "k",
|
|
6126
|
-
"%6B": "k",
|
|
6127
|
-
"%6c": "l",
|
|
6128
|
-
"%6C": "l",
|
|
6129
|
-
"%6d": "m",
|
|
6130
|
-
"%6D": "m",
|
|
6131
|
-
"%6e": "n",
|
|
6132
|
-
"%6E": "n",
|
|
6133
|
-
"%6f": "o",
|
|
6134
|
-
"%6F": "o",
|
|
6135
|
-
"%70": "p",
|
|
6136
|
-
"%71": "q",
|
|
6137
|
-
"%72": "r",
|
|
6138
|
-
"%73": "s",
|
|
6139
|
-
"%74": "t",
|
|
6140
|
-
"%75": "u",
|
|
6141
|
-
"%76": "v",
|
|
6142
|
-
"%77": "w",
|
|
6143
|
-
"%78": "x",
|
|
6144
|
-
"%79": "y",
|
|
6145
|
-
"%7a": "z",
|
|
6146
|
-
"%7A": "z",
|
|
6147
|
-
"%7b": "{",
|
|
6148
|
-
"%7B": "{",
|
|
6149
|
-
"%7c": "|",
|
|
6150
|
-
"%7C": "|",
|
|
6151
|
-
"%7d": "}",
|
|
6152
|
-
"%7D": "}",
|
|
6153
|
-
"%7e": "~",
|
|
6154
|
-
"%7E": "~",
|
|
6155
|
-
"%7f": "",
|
|
6156
|
-
"%7F": "",
|
|
6157
|
-
"%80": "",
|
|
6158
|
-
"%81": "",
|
|
6159
|
-
"%82": "",
|
|
6160
|
-
"%83": "",
|
|
6161
|
-
"%84": "",
|
|
6162
|
-
"%85": "
",
|
|
6163
|
-
"%86": "",
|
|
6164
|
-
"%87": "",
|
|
6165
|
-
"%88": "",
|
|
6166
|
-
"%89": "",
|
|
6167
|
-
"%8a": "",
|
|
6168
|
-
"%8A": "",
|
|
6169
|
-
"%8b": "",
|
|
6170
|
-
"%8B": "",
|
|
6171
|
-
"%8c": "",
|
|
6172
|
-
"%8C": "",
|
|
6173
|
-
"%8d": "",
|
|
6174
|
-
"%8D": "",
|
|
6175
|
-
"%8e": "",
|
|
6176
|
-
"%8E": "",
|
|
6177
|
-
"%8f": "",
|
|
6178
|
-
"%8F": "",
|
|
6179
|
-
"%90": "",
|
|
6180
|
-
"%91": "",
|
|
6181
|
-
"%92": "",
|
|
6182
|
-
"%93": "",
|
|
6183
|
-
"%94": "",
|
|
6184
|
-
"%95": "",
|
|
6185
|
-
"%96": "",
|
|
6186
|
-
"%97": "",
|
|
6187
|
-
"%98": "",
|
|
6188
|
-
"%99": "",
|
|
6189
|
-
"%9a": "",
|
|
6190
|
-
"%9A": "",
|
|
6191
|
-
"%9b": "",
|
|
6192
|
-
"%9B": "",
|
|
6193
|
-
"%9c": "",
|
|
6194
|
-
"%9C": "",
|
|
6195
|
-
"%9d": "",
|
|
6196
|
-
"%9D": "",
|
|
6197
|
-
"%9e": "",
|
|
6198
|
-
"%9E": "",
|
|
6199
|
-
"%9f": "",
|
|
6200
|
-
"%9F": "",
|
|
6201
|
-
"%a0": "\xA0",
|
|
6202
|
-
"%A0": "\xA0",
|
|
6203
|
-
"%a1": "¡",
|
|
6204
|
-
"%A1": "¡",
|
|
6205
|
-
"%a2": "¢",
|
|
6206
|
-
"%A2": "¢",
|
|
6207
|
-
"%a3": "£",
|
|
6208
|
-
"%A3": "£",
|
|
6209
|
-
"%a4": "¤",
|
|
6210
|
-
"%A4": "¤",
|
|
6211
|
-
"%a5": "¥",
|
|
6212
|
-
"%A5": "¥",
|
|
6213
|
-
"%a6": "¦",
|
|
6214
|
-
"%A6": "¦",
|
|
6215
|
-
"%a7": "§",
|
|
6216
|
-
"%A7": "§",
|
|
6217
|
-
"%a8": "¨",
|
|
6218
|
-
"%A8": "¨",
|
|
6219
|
-
"%a9": "©",
|
|
6220
|
-
"%A9": "©",
|
|
6221
|
-
"%aa": "ª",
|
|
6222
|
-
"%Aa": "ª",
|
|
6223
|
-
"%aA": "ª",
|
|
6224
|
-
"%AA": "ª",
|
|
6225
|
-
"%ab": "«",
|
|
6226
|
-
"%Ab": "«",
|
|
6227
|
-
"%aB": "«",
|
|
6228
|
-
"%AB": "«",
|
|
6229
|
-
"%ac": "¬",
|
|
6230
|
-
"%Ac": "¬",
|
|
6231
|
-
"%aC": "¬",
|
|
6232
|
-
"%AC": "¬",
|
|
6233
|
-
"%ad": "",
|
|
6234
|
-
"%Ad": "",
|
|
6235
|
-
"%aD": "",
|
|
6236
|
-
"%AD": "",
|
|
6237
|
-
"%ae": "®",
|
|
6238
|
-
"%Ae": "®",
|
|
6239
|
-
"%aE": "®",
|
|
6240
|
-
"%AE": "®",
|
|
6241
|
-
"%af": "¯",
|
|
6242
|
-
"%Af": "¯",
|
|
6243
|
-
"%aF": "¯",
|
|
6244
|
-
"%AF": "¯",
|
|
6245
|
-
"%b0": "°",
|
|
6246
|
-
"%B0": "°",
|
|
6247
|
-
"%b1": "±",
|
|
6248
|
-
"%B1": "±",
|
|
6249
|
-
"%b2": "²",
|
|
6250
|
-
"%B2": "²",
|
|
6251
|
-
"%b3": "³",
|
|
6252
|
-
"%B3": "³",
|
|
6253
|
-
"%b4": "´",
|
|
6254
|
-
"%B4": "´",
|
|
6255
|
-
"%b5": "µ",
|
|
6256
|
-
"%B5": "µ",
|
|
6257
|
-
"%b6": "¶",
|
|
6258
|
-
"%B6": "¶",
|
|
6259
|
-
"%b7": "·",
|
|
6260
|
-
"%B7": "·",
|
|
6261
|
-
"%b8": "¸",
|
|
6262
|
-
"%B8": "¸",
|
|
6263
|
-
"%b9": "¹",
|
|
6264
|
-
"%B9": "¹",
|
|
6265
|
-
"%ba": "º",
|
|
6266
|
-
"%Ba": "º",
|
|
6267
|
-
"%bA": "º",
|
|
6268
|
-
"%BA": "º",
|
|
6269
|
-
"%bb": "»",
|
|
6270
|
-
"%Bb": "»",
|
|
6271
|
-
"%bB": "»",
|
|
6272
|
-
"%BB": "»",
|
|
6273
|
-
"%bc": "¼",
|
|
6274
|
-
"%Bc": "¼",
|
|
6275
|
-
"%bC": "¼",
|
|
6276
|
-
"%BC": "¼",
|
|
6277
|
-
"%bd": "½",
|
|
6278
|
-
"%Bd": "½",
|
|
6279
|
-
"%bD": "½",
|
|
6280
|
-
"%BD": "½",
|
|
6281
|
-
"%be": "¾",
|
|
6282
|
-
"%Be": "¾",
|
|
6283
|
-
"%bE": "¾",
|
|
6284
|
-
"%BE": "¾",
|
|
6285
|
-
"%bf": "¿",
|
|
6286
|
-
"%Bf": "¿",
|
|
6287
|
-
"%bF": "¿",
|
|
6288
|
-
"%BF": "¿",
|
|
6289
|
-
"%c0": "À",
|
|
6290
|
-
"%C0": "À",
|
|
6291
|
-
"%c1": "Á",
|
|
6292
|
-
"%C1": "Á",
|
|
6293
|
-
"%c2": "Â",
|
|
6294
|
-
"%C2": "Â",
|
|
6295
|
-
"%c3": "Ã",
|
|
6296
|
-
"%C3": "Ã",
|
|
6297
|
-
"%c4": "Ä",
|
|
6298
|
-
"%C4": "Ä",
|
|
6299
|
-
"%c5": "Å",
|
|
6300
|
-
"%C5": "Å",
|
|
6301
|
-
"%c6": "Æ",
|
|
6302
|
-
"%C6": "Æ",
|
|
6303
|
-
"%c7": "Ç",
|
|
6304
|
-
"%C7": "Ç",
|
|
6305
|
-
"%c8": "È",
|
|
6306
|
-
"%C8": "È",
|
|
6307
|
-
"%c9": "É",
|
|
6308
|
-
"%C9": "É",
|
|
6309
|
-
"%ca": "Ê",
|
|
6310
|
-
"%Ca": "Ê",
|
|
6311
|
-
"%cA": "Ê",
|
|
6312
|
-
"%CA": "Ê",
|
|
6313
|
-
"%cb": "Ë",
|
|
6314
|
-
"%Cb": "Ë",
|
|
6315
|
-
"%cB": "Ë",
|
|
6316
|
-
"%CB": "Ë",
|
|
6317
|
-
"%cc": "Ì",
|
|
6318
|
-
"%Cc": "Ì",
|
|
6319
|
-
"%cC": "Ì",
|
|
6320
|
-
"%CC": "Ì",
|
|
6321
|
-
"%cd": "Í",
|
|
6322
|
-
"%Cd": "Í",
|
|
6323
|
-
"%cD": "Í",
|
|
6324
|
-
"%CD": "Í",
|
|
6325
|
-
"%ce": "Î",
|
|
6326
|
-
"%Ce": "Î",
|
|
6327
|
-
"%cE": "Î",
|
|
6328
|
-
"%CE": "Î",
|
|
6329
|
-
"%cf": "Ï",
|
|
6330
|
-
"%Cf": "Ï",
|
|
6331
|
-
"%cF": "Ï",
|
|
6332
|
-
"%CF": "Ï",
|
|
6333
|
-
"%d0": "Ð",
|
|
6334
|
-
"%D0": "Ð",
|
|
6335
|
-
"%d1": "Ñ",
|
|
6336
|
-
"%D1": "Ñ",
|
|
6337
|
-
"%d2": "Ò",
|
|
6338
|
-
"%D2": "Ò",
|
|
6339
|
-
"%d3": "Ó",
|
|
6340
|
-
"%D3": "Ó",
|
|
6341
|
-
"%d4": "Ô",
|
|
6342
|
-
"%D4": "Ô",
|
|
6343
|
-
"%d5": "Õ",
|
|
6344
|
-
"%D5": "Õ",
|
|
6345
|
-
"%d6": "Ö",
|
|
6346
|
-
"%D6": "Ö",
|
|
6347
|
-
"%d7": "×",
|
|
6348
|
-
"%D7": "×",
|
|
6349
|
-
"%d8": "Ø",
|
|
6350
|
-
"%D8": "Ø",
|
|
6351
|
-
"%d9": "Ù",
|
|
6352
|
-
"%D9": "Ù",
|
|
6353
|
-
"%da": "Ú",
|
|
6354
|
-
"%Da": "Ú",
|
|
6355
|
-
"%dA": "Ú",
|
|
6356
|
-
"%DA": "Ú",
|
|
6357
|
-
"%db": "Û",
|
|
6358
|
-
"%Db": "Û",
|
|
6359
|
-
"%dB": "Û",
|
|
6360
|
-
"%DB": "Û",
|
|
6361
|
-
"%dc": "Ü",
|
|
6362
|
-
"%Dc": "Ü",
|
|
6363
|
-
"%dC": "Ü",
|
|
6364
|
-
"%DC": "Ü",
|
|
6365
|
-
"%dd": "Ý",
|
|
6366
|
-
"%Dd": "Ý",
|
|
6367
|
-
"%dD": "Ý",
|
|
6368
|
-
"%DD": "Ý",
|
|
6369
|
-
"%de": "Þ",
|
|
6370
|
-
"%De": "Þ",
|
|
6371
|
-
"%dE": "Þ",
|
|
6372
|
-
"%DE": "Þ",
|
|
6373
|
-
"%df": "ß",
|
|
6374
|
-
"%Df": "ß",
|
|
6375
|
-
"%dF": "ß",
|
|
6376
|
-
"%DF": "ß",
|
|
6377
|
-
"%e0": "à",
|
|
6378
|
-
"%E0": "à",
|
|
6379
|
-
"%e1": "á",
|
|
6380
|
-
"%E1": "á",
|
|
6381
|
-
"%e2": "â",
|
|
6382
|
-
"%E2": "â",
|
|
6383
|
-
"%e3": "ã",
|
|
6384
|
-
"%E3": "ã",
|
|
6385
|
-
"%e4": "ä",
|
|
6386
|
-
"%E4": "ä",
|
|
6387
|
-
"%e5": "å",
|
|
6388
|
-
"%E5": "å",
|
|
6389
|
-
"%e6": "æ",
|
|
6390
|
-
"%E6": "æ",
|
|
6391
|
-
"%e7": "ç",
|
|
6392
|
-
"%E7": "ç",
|
|
6393
|
-
"%e8": "è",
|
|
6394
|
-
"%E8": "è",
|
|
6395
|
-
"%e9": "é",
|
|
6396
|
-
"%E9": "é",
|
|
6397
|
-
"%ea": "ê",
|
|
6398
|
-
"%Ea": "ê",
|
|
6399
|
-
"%eA": "ê",
|
|
6400
|
-
"%EA": "ê",
|
|
6401
|
-
"%eb": "ë",
|
|
6402
|
-
"%Eb": "ë",
|
|
6403
|
-
"%eB": "ë",
|
|
6404
|
-
"%EB": "ë",
|
|
6405
|
-
"%ec": "ì",
|
|
6406
|
-
"%Ec": "ì",
|
|
6407
|
-
"%eC": "ì",
|
|
6408
|
-
"%EC": "ì",
|
|
6409
|
-
"%ed": "í",
|
|
6410
|
-
"%Ed": "í",
|
|
6411
|
-
"%eD": "í",
|
|
6412
|
-
"%ED": "í",
|
|
6413
|
-
"%ee": "î",
|
|
6414
|
-
"%Ee": "î",
|
|
6415
|
-
"%eE": "î",
|
|
6416
|
-
"%EE": "î",
|
|
6417
|
-
"%ef": "ï",
|
|
6418
|
-
"%Ef": "ï",
|
|
6419
|
-
"%eF": "ï",
|
|
6420
|
-
"%EF": "ï",
|
|
6421
|
-
"%f0": "ð",
|
|
6422
|
-
"%F0": "ð",
|
|
6423
|
-
"%f1": "ñ",
|
|
6424
|
-
"%F1": "ñ",
|
|
6425
|
-
"%f2": "ò",
|
|
6426
|
-
"%F2": "ò",
|
|
6427
|
-
"%f3": "ó",
|
|
6428
|
-
"%F3": "ó",
|
|
6429
|
-
"%f4": "ô",
|
|
6430
|
-
"%F4": "ô",
|
|
6431
|
-
"%f5": "õ",
|
|
6432
|
-
"%F5": "õ",
|
|
6433
|
-
"%f6": "ö",
|
|
6434
|
-
"%F6": "ö",
|
|
6435
|
-
"%f7": "÷",
|
|
6436
|
-
"%F7": "÷",
|
|
6437
|
-
"%f8": "ø",
|
|
6438
|
-
"%F8": "ø",
|
|
6439
|
-
"%f9": "ù",
|
|
6440
|
-
"%F9": "ù",
|
|
6441
|
-
"%fa": "ú",
|
|
6442
|
-
"%Fa": "ú",
|
|
6443
|
-
"%fA": "ú",
|
|
6444
|
-
"%FA": "ú",
|
|
6445
|
-
"%fb": "û",
|
|
6446
|
-
"%Fb": "û",
|
|
6447
|
-
"%fB": "û",
|
|
6448
|
-
"%FB": "û",
|
|
6449
|
-
"%fc": "ü",
|
|
6450
|
-
"%Fc": "ü",
|
|
6451
|
-
"%fC": "ü",
|
|
6452
|
-
"%FC": "ü",
|
|
6453
|
-
"%fd": "ý",
|
|
6454
|
-
"%Fd": "ý",
|
|
6455
|
-
"%fD": "ý",
|
|
6456
|
-
"%FD": "ý",
|
|
6457
|
-
"%fe": "þ",
|
|
6458
|
-
"%Fe": "þ",
|
|
6459
|
-
"%fE": "þ",
|
|
6460
|
-
"%FE": "þ",
|
|
6461
|
-
"%ff": "ÿ",
|
|
6462
|
-
"%Ff": "ÿ",
|
|
6463
|
-
"%fF": "ÿ",
|
|
6464
|
-
"%FF": "ÿ"
|
|
6465
|
-
};
|
|
6466
|
-
function encodedReplacer(match) {
|
|
6467
|
-
return EncodedLookup[match];
|
|
6468
|
-
}
|
|
6469
|
-
const STATE_KEY = 0;
|
|
6470
|
-
const STATE_VALUE = 1;
|
|
6471
|
-
const STATE_CHARSET = 2;
|
|
6472
|
-
const STATE_LANG = 3;
|
|
6473
|
-
function parseParams(str) {
|
|
6474
|
-
const res = [];
|
|
6475
|
-
let state = STATE_KEY;
|
|
6476
|
-
let charset = "";
|
|
6477
|
-
let inquote = false;
|
|
6478
|
-
let escaping = false;
|
|
6479
|
-
let p = 0;
|
|
6480
|
-
let tmp = "";
|
|
6481
|
-
const len = str.length;
|
|
6482
|
-
for (var i = 0; i < len; ++i) {
|
|
6483
|
-
const char = str[i];
|
|
6484
|
-
if (char === "\\" && inquote) if (escaping) escaping = false;
|
|
6485
|
-
else {
|
|
6486
|
-
escaping = true;
|
|
6487
|
-
continue;
|
|
6488
|
-
}
|
|
6489
|
-
else if (char === "\"") if (!escaping) {
|
|
6490
|
-
if (inquote) {
|
|
6491
|
-
inquote = false;
|
|
6492
|
-
state = STATE_KEY;
|
|
6493
|
-
while (i + 1 < len && str[i + 1] !== ";") ++i;
|
|
6494
|
-
} else inquote = true;
|
|
6495
|
-
continue;
|
|
6496
|
-
} else escaping = false;
|
|
6497
|
-
else {
|
|
6498
|
-
if (escaping && inquote) tmp += "\\";
|
|
6499
|
-
escaping = false;
|
|
6500
|
-
if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") {
|
|
6501
|
-
if (state === STATE_CHARSET) {
|
|
6502
|
-
state = STATE_LANG;
|
|
6503
|
-
charset = tmp.substring(1);
|
|
6504
|
-
} else state = STATE_VALUE;
|
|
6505
|
-
tmp = "";
|
|
6506
|
-
continue;
|
|
6507
|
-
} else if (state === STATE_KEY && (char === "*" || char === "=") && res.length) {
|
|
6508
|
-
state = char === "*" ? STATE_CHARSET : STATE_VALUE;
|
|
6509
|
-
res[p] = [tmp, void 0];
|
|
6510
|
-
tmp = "";
|
|
6511
|
-
continue;
|
|
6512
|
-
} else if (!inquote && char === ";") {
|
|
6513
|
-
state = STATE_KEY;
|
|
6514
|
-
if (charset) {
|
|
6515
|
-
if (tmp.length) tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), "binary", charset);
|
|
6516
|
-
charset = "";
|
|
6517
|
-
} else if (tmp.length) tmp = decodeText(tmp, "binary", "utf8");
|
|
6518
|
-
if (res[p] === void 0) res[p] = tmp;
|
|
6519
|
-
else res[p][1] = tmp;
|
|
6520
|
-
tmp = "";
|
|
6521
|
-
++p;
|
|
6522
|
-
continue;
|
|
6523
|
-
} else if (!inquote && (char === " " || char === " ")) continue;
|
|
6524
|
-
}
|
|
6525
|
-
tmp += char;
|
|
6526
|
-
}
|
|
6527
|
-
if (charset && tmp.length) tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), "binary", charset);
|
|
6528
|
-
else if (tmp) tmp = decodeText(tmp, "binary", "utf8");
|
|
6529
|
-
if (res[p] === void 0) {
|
|
6530
|
-
if (tmp) res[p] = tmp;
|
|
6531
|
-
} else res[p][1] = tmp;
|
|
6532
|
-
return res;
|
|
6533
|
-
}
|
|
6534
|
-
module.exports = parseParams;
|
|
6535
|
-
}));
|
|
6536
|
-
//#endregion
|
|
6537
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/basename.js
|
|
6538
|
-
var require_basename = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6539
|
-
module.exports = function basename(path) {
|
|
6540
|
-
if (typeof path !== "string") return "";
|
|
6541
|
-
for (var i = path.length - 1; i >= 0; --i) switch (path.charCodeAt(i)) {
|
|
6542
|
-
case 47:
|
|
6543
|
-
case 92:
|
|
6544
|
-
path = path.slice(i + 1);
|
|
6545
|
-
return path === ".." || path === "." ? "" : path;
|
|
6546
|
-
}
|
|
6547
|
-
return path === ".." || path === "." ? "" : path;
|
|
6548
|
-
};
|
|
6549
|
-
}));
|
|
6550
|
-
//#endregion
|
|
6551
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/types/multipart.js
|
|
6552
|
-
var require_multipart$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6553
|
-
const { Readable: Readable$1 } = __require("node:stream");
|
|
6554
|
-
const { inherits: inherits$1 } = __require("node:util");
|
|
6555
|
-
const Dicer = require_Dicer();
|
|
6556
|
-
const parseParams = require_parseParams();
|
|
6557
|
-
const decodeText = require_decodeText();
|
|
6558
|
-
const basename = require_basename();
|
|
6559
|
-
const getLimit = require_getLimit();
|
|
6560
|
-
const RE_BOUNDARY = /^boundary$/i;
|
|
6561
|
-
const RE_FIELD = /^form-data$/i;
|
|
6562
|
-
const RE_CHARSET = /^charset$/i;
|
|
6563
|
-
const RE_FILENAME = /^filename$/i;
|
|
6564
|
-
const RE_NAME = /^name$/i;
|
|
6565
|
-
Multipart.detect = /^multipart\/form-data/i;
|
|
6566
|
-
function Multipart(boy, cfg) {
|
|
6567
|
-
let i;
|
|
6568
|
-
let len;
|
|
6569
|
-
const self = this;
|
|
6570
|
-
let boundary;
|
|
6571
|
-
const limits = cfg.limits;
|
|
6572
|
-
const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => contentType === "application/octet-stream" || fileName !== void 0);
|
|
6573
|
-
const parsedConType = cfg.parsedConType || [];
|
|
6574
|
-
const defCharset = cfg.defCharset || "utf8";
|
|
6575
|
-
const preservePath = cfg.preservePath;
|
|
6576
|
-
const fileOpts = { highWaterMark: cfg.fileHwm };
|
|
6577
|
-
for (i = 0, len = parsedConType.length; i < len; ++i) if (Array.isArray(parsedConType[i]) && RE_BOUNDARY.test(parsedConType[i][0])) {
|
|
6578
|
-
boundary = parsedConType[i][1];
|
|
6579
|
-
break;
|
|
6580
|
-
}
|
|
6581
|
-
function checkFinished() {
|
|
6582
|
-
if (nends === 0 && finished && !boy._done) {
|
|
6583
|
-
finished = false;
|
|
6584
|
-
self.end();
|
|
6585
|
-
}
|
|
6586
|
-
}
|
|
6587
|
-
if (typeof boundary !== "string") throw new Error("Multipart: Boundary not found");
|
|
6588
|
-
const fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024);
|
|
6589
|
-
const fileSizeLimit = getLimit(limits, "fileSize", Infinity);
|
|
6590
|
-
const filesLimit = getLimit(limits, "files", Infinity);
|
|
6591
|
-
const fieldsLimit = getLimit(limits, "fields", Infinity);
|
|
6592
|
-
const partsLimit = getLimit(limits, "parts", Infinity);
|
|
6593
|
-
const headerPairsLimit = getLimit(limits, "headerPairs", 2e3);
|
|
6594
|
-
const headerSizeLimit = getLimit(limits, "headerSize", 80 * 1024);
|
|
6595
|
-
let nfiles = 0;
|
|
6596
|
-
let nfields = 0;
|
|
6597
|
-
let nends = 0;
|
|
6598
|
-
let curFile;
|
|
6599
|
-
let curField;
|
|
6600
|
-
let finished = false;
|
|
6601
|
-
this._needDrain = false;
|
|
6602
|
-
this._pause = false;
|
|
6603
|
-
this._cb = void 0;
|
|
6604
|
-
this._nparts = 0;
|
|
6605
|
-
this._boy = boy;
|
|
6606
|
-
this.parser = new Dicer({
|
|
6607
|
-
boundary,
|
|
6608
|
-
maxHeaderPairs: headerPairsLimit,
|
|
6609
|
-
maxHeaderSize: headerSizeLimit,
|
|
6610
|
-
partHwm: fileOpts.highWaterMark,
|
|
6611
|
-
highWaterMark: cfg.highWaterMark
|
|
6612
|
-
});
|
|
6613
|
-
this.parser.on("drain", function() {
|
|
6614
|
-
self._needDrain = false;
|
|
6615
|
-
if (self._cb && !self._pause) {
|
|
6616
|
-
const cb = self._cb;
|
|
6617
|
-
self._cb = void 0;
|
|
6618
|
-
cb();
|
|
6619
|
-
}
|
|
6620
|
-
}).on("part", function onPart(part) {
|
|
6621
|
-
if (++self._nparts > partsLimit) {
|
|
6622
|
-
self.parser.removeListener("part", onPart);
|
|
6623
|
-
self.parser.on("part", skipPart);
|
|
6624
|
-
boy.hitPartsLimit = true;
|
|
6625
|
-
boy.emit("partsLimit");
|
|
6626
|
-
return skipPart(part);
|
|
6627
|
-
}
|
|
6628
|
-
if (curField) {
|
|
6629
|
-
const field = curField;
|
|
6630
|
-
field.emit("end");
|
|
6631
|
-
field.removeAllListeners("end");
|
|
6632
|
-
}
|
|
6633
|
-
part.on("header", function(header) {
|
|
6634
|
-
let contype;
|
|
6635
|
-
let fieldname;
|
|
6636
|
-
let parsed;
|
|
6637
|
-
let charset;
|
|
6638
|
-
let encoding;
|
|
6639
|
-
let filename;
|
|
6640
|
-
let nsize = 0;
|
|
6641
|
-
if (header["content-type"]) {
|
|
6642
|
-
parsed = parseParams(header["content-type"][0]);
|
|
6643
|
-
if (parsed[0]) {
|
|
6644
|
-
contype = parsed[0].toLowerCase();
|
|
6645
|
-
for (i = 0, len = parsed.length; i < len; ++i) if (RE_CHARSET.test(parsed[i][0])) {
|
|
6646
|
-
charset = parsed[i][1].toLowerCase();
|
|
6647
|
-
break;
|
|
6648
|
-
}
|
|
6649
|
-
}
|
|
6650
|
-
}
|
|
6651
|
-
if (contype === void 0) contype = "text/plain";
|
|
6652
|
-
if (charset === void 0) charset = defCharset;
|
|
6653
|
-
if (header["content-disposition"]) {
|
|
6654
|
-
parsed = parseParams(header["content-disposition"][0]);
|
|
6655
|
-
if (!RE_FIELD.test(parsed[0])) return skipPart(part);
|
|
6656
|
-
for (i = 0, len = parsed.length; i < len; ++i) if (RE_NAME.test(parsed[i][0])) fieldname = parsed[i][1];
|
|
6657
|
-
else if (RE_FILENAME.test(parsed[i][0])) {
|
|
6658
|
-
filename = parsed[i][1];
|
|
6659
|
-
if (!preservePath) filename = basename(filename);
|
|
6660
|
-
}
|
|
6661
|
-
} else return skipPart(part);
|
|
6662
|
-
if (header["content-transfer-encoding"]) encoding = header["content-transfer-encoding"][0].toLowerCase();
|
|
6663
|
-
else encoding = "7bit";
|
|
6664
|
-
let onData, onEnd;
|
|
6665
|
-
if (isPartAFile(fieldname, contype, filename)) {
|
|
6666
|
-
if (nfiles === filesLimit) {
|
|
6667
|
-
if (!boy.hitFilesLimit) {
|
|
6668
|
-
boy.hitFilesLimit = true;
|
|
6669
|
-
boy.emit("filesLimit");
|
|
6670
|
-
}
|
|
6671
|
-
return skipPart(part);
|
|
6672
|
-
}
|
|
6673
|
-
++nfiles;
|
|
6674
|
-
if (boy.listenerCount("file") === 0) {
|
|
6675
|
-
self.parser._ignore();
|
|
6676
|
-
return;
|
|
6677
|
-
}
|
|
6678
|
-
++nends;
|
|
6679
|
-
const file = new FileStream(fileOpts);
|
|
6680
|
-
curFile = file;
|
|
6681
|
-
file.on("end", function() {
|
|
6682
|
-
--nends;
|
|
6683
|
-
self._pause = false;
|
|
6684
|
-
checkFinished();
|
|
6685
|
-
if (self._cb && !self._needDrain) {
|
|
6686
|
-
const cb = self._cb;
|
|
6687
|
-
self._cb = void 0;
|
|
6688
|
-
cb();
|
|
6689
|
-
}
|
|
6690
|
-
});
|
|
6691
|
-
file._read = function(n) {
|
|
6692
|
-
if (!self._pause) return;
|
|
6693
|
-
self._pause = false;
|
|
6694
|
-
if (self._cb && !self._needDrain) {
|
|
6695
|
-
const cb = self._cb;
|
|
6696
|
-
self._cb = void 0;
|
|
6697
|
-
cb();
|
|
6698
|
-
}
|
|
6699
|
-
};
|
|
6700
|
-
boy.emit("file", fieldname, file, filename, encoding, contype);
|
|
6701
|
-
onData = function(data) {
|
|
6702
|
-
if ((nsize += data.length) > fileSizeLimit) {
|
|
6703
|
-
const extralen = fileSizeLimit - nsize + data.length;
|
|
6704
|
-
if (extralen > 0) file.push(data.slice(0, extralen));
|
|
6705
|
-
file.truncated = true;
|
|
6706
|
-
file.bytesRead = fileSizeLimit;
|
|
6707
|
-
part.removeAllListeners("data");
|
|
6708
|
-
file.emit("limit");
|
|
6709
|
-
return;
|
|
6710
|
-
} else if (!file.push(data)) self._pause = true;
|
|
6711
|
-
file.bytesRead = nsize;
|
|
6712
|
-
};
|
|
6713
|
-
onEnd = function() {
|
|
6714
|
-
curFile = void 0;
|
|
6715
|
-
file.push(null);
|
|
6716
|
-
};
|
|
6717
|
-
} else {
|
|
6718
|
-
if (nfields === fieldsLimit) {
|
|
6719
|
-
if (!boy.hitFieldsLimit) {
|
|
6720
|
-
boy.hitFieldsLimit = true;
|
|
6721
|
-
boy.emit("fieldsLimit");
|
|
6722
|
-
}
|
|
6723
|
-
return skipPart(part);
|
|
6724
|
-
}
|
|
6725
|
-
++nfields;
|
|
6726
|
-
++nends;
|
|
6727
|
-
let buffer = "";
|
|
6728
|
-
let truncated = false;
|
|
6729
|
-
curField = part;
|
|
6730
|
-
onData = function(data) {
|
|
6731
|
-
if ((nsize += data.length) > fieldSizeLimit) {
|
|
6732
|
-
const extralen = fieldSizeLimit - (nsize - data.length);
|
|
6733
|
-
buffer += data.toString("binary", 0, extralen);
|
|
6734
|
-
truncated = true;
|
|
6735
|
-
part.removeAllListeners("data");
|
|
6736
|
-
} else buffer += data.toString("binary");
|
|
6737
|
-
};
|
|
6738
|
-
onEnd = function() {
|
|
6739
|
-
curField = void 0;
|
|
6740
|
-
if (buffer.length) buffer = decodeText(buffer, "binary", charset);
|
|
6741
|
-
boy.emit("field", fieldname, buffer, false, truncated, encoding, contype);
|
|
6742
|
-
--nends;
|
|
6743
|
-
checkFinished();
|
|
6744
|
-
};
|
|
6745
|
-
}
|
|
6746
|
-
part._readableState.sync = false;
|
|
6747
|
-
part.on("data", onData);
|
|
6748
|
-
part.on("end", onEnd);
|
|
6749
|
-
}).on("error", function(err) {
|
|
6750
|
-
if (curFile) curFile.emit("error", err);
|
|
6751
|
-
});
|
|
6752
|
-
}).on("error", function(err) {
|
|
6753
|
-
boy.emit("error", err);
|
|
6754
|
-
}).on("finish", function() {
|
|
6755
|
-
finished = true;
|
|
6756
|
-
checkFinished();
|
|
6757
|
-
});
|
|
6758
|
-
}
|
|
6759
|
-
Multipart.prototype.write = function(chunk, cb) {
|
|
6760
|
-
const r = this.parser.write(chunk);
|
|
6761
|
-
if (r && !this._pause) cb();
|
|
6762
|
-
else {
|
|
6763
|
-
this._needDrain = !r;
|
|
6764
|
-
this._cb = cb;
|
|
6765
|
-
}
|
|
6766
|
-
};
|
|
6767
|
-
Multipart.prototype.end = function() {
|
|
6768
|
-
const self = this;
|
|
6769
|
-
if (self.parser.writable) self.parser.end();
|
|
6770
|
-
else if (!self._boy._done) process.nextTick(function() {
|
|
6771
|
-
self._boy._done = true;
|
|
6772
|
-
self._boy.emit("finish");
|
|
6773
|
-
});
|
|
6774
|
-
};
|
|
6775
|
-
function skipPart(part) {
|
|
6776
|
-
part.resume();
|
|
6777
|
-
}
|
|
6778
|
-
function FileStream(opts) {
|
|
6779
|
-
Readable$1.call(this, opts);
|
|
6780
|
-
this.bytesRead = 0;
|
|
6781
|
-
this.truncated = false;
|
|
6782
|
-
}
|
|
6783
|
-
inherits$1(FileStream, Readable$1);
|
|
6784
|
-
FileStream.prototype._read = function(n) {};
|
|
6785
|
-
module.exports = Multipart;
|
|
6786
|
-
}));
|
|
6787
|
-
//#endregion
|
|
6788
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/utils/Decoder.js
|
|
6789
|
-
var require_Decoder = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6790
|
-
const RE_PLUS = /\+/g;
|
|
6791
|
-
const HEX = [
|
|
6792
|
-
0,
|
|
6793
|
-
0,
|
|
6794
|
-
0,
|
|
6795
|
-
0,
|
|
6796
|
-
0,
|
|
6797
|
-
0,
|
|
6798
|
-
0,
|
|
6799
|
-
0,
|
|
6800
|
-
0,
|
|
6801
|
-
0,
|
|
6802
|
-
0,
|
|
6803
|
-
0,
|
|
6804
|
-
0,
|
|
6805
|
-
0,
|
|
6806
|
-
0,
|
|
6807
|
-
0,
|
|
6808
|
-
0,
|
|
6809
|
-
0,
|
|
6810
|
-
0,
|
|
6811
|
-
0,
|
|
6812
|
-
0,
|
|
6813
|
-
0,
|
|
6814
|
-
0,
|
|
6815
|
-
0,
|
|
6816
|
-
0,
|
|
6817
|
-
0,
|
|
6818
|
-
0,
|
|
6819
|
-
0,
|
|
6820
|
-
0,
|
|
6821
|
-
0,
|
|
6822
|
-
0,
|
|
6823
|
-
0,
|
|
6824
|
-
0,
|
|
6825
|
-
0,
|
|
6826
|
-
0,
|
|
6827
|
-
0,
|
|
6828
|
-
0,
|
|
6829
|
-
0,
|
|
6830
|
-
0,
|
|
6831
|
-
0,
|
|
6832
|
-
0,
|
|
6833
|
-
0,
|
|
6834
|
-
0,
|
|
6835
|
-
0,
|
|
6836
|
-
0,
|
|
6837
|
-
0,
|
|
6838
|
-
0,
|
|
6839
|
-
0,
|
|
6840
|
-
1,
|
|
6841
|
-
1,
|
|
6842
|
-
1,
|
|
6843
|
-
1,
|
|
6844
|
-
1,
|
|
6845
|
-
1,
|
|
6846
|
-
1,
|
|
6847
|
-
1,
|
|
6848
|
-
1,
|
|
6849
|
-
1,
|
|
6850
|
-
0,
|
|
6851
|
-
0,
|
|
6852
|
-
0,
|
|
6853
|
-
0,
|
|
6854
|
-
0,
|
|
6855
|
-
0,
|
|
6856
|
-
0,
|
|
6857
|
-
1,
|
|
6858
|
-
1,
|
|
6859
|
-
1,
|
|
6860
|
-
1,
|
|
6861
|
-
1,
|
|
6862
|
-
1,
|
|
6863
|
-
0,
|
|
6864
|
-
0,
|
|
6865
|
-
0,
|
|
6866
|
-
0,
|
|
6867
|
-
0,
|
|
6868
|
-
0,
|
|
6869
|
-
0,
|
|
6870
|
-
0,
|
|
6871
|
-
0,
|
|
6872
|
-
0,
|
|
6873
|
-
0,
|
|
6874
|
-
0,
|
|
6875
|
-
0,
|
|
6876
|
-
0,
|
|
6877
|
-
0,
|
|
6878
|
-
0,
|
|
6879
|
-
0,
|
|
6880
|
-
0,
|
|
6881
|
-
0,
|
|
6882
|
-
0,
|
|
6883
|
-
0,
|
|
6884
|
-
0,
|
|
6885
|
-
0,
|
|
6886
|
-
0,
|
|
6887
|
-
0,
|
|
6888
|
-
0,
|
|
6889
|
-
1,
|
|
6890
|
-
1,
|
|
6891
|
-
1,
|
|
6892
|
-
1,
|
|
6893
|
-
1,
|
|
6894
|
-
1,
|
|
6895
|
-
0,
|
|
6896
|
-
0,
|
|
6897
|
-
0,
|
|
6898
|
-
0,
|
|
6899
|
-
0,
|
|
6900
|
-
0,
|
|
6901
|
-
0,
|
|
6902
|
-
0,
|
|
6903
|
-
0,
|
|
6904
|
-
0,
|
|
6905
|
-
0,
|
|
6906
|
-
0,
|
|
6907
|
-
0,
|
|
6908
|
-
0,
|
|
6909
|
-
0,
|
|
6910
|
-
0,
|
|
6911
|
-
0,
|
|
6912
|
-
0,
|
|
6913
|
-
0,
|
|
6914
|
-
0,
|
|
6915
|
-
0,
|
|
6916
|
-
0,
|
|
6917
|
-
0,
|
|
6918
|
-
0,
|
|
6919
|
-
0
|
|
6920
|
-
];
|
|
6921
|
-
function Decoder() {
|
|
6922
|
-
this.buffer = void 0;
|
|
6923
|
-
}
|
|
6924
|
-
Decoder.prototype.write = function(str) {
|
|
6925
|
-
str = str.replace(RE_PLUS, " ");
|
|
6926
|
-
let res = "";
|
|
6927
|
-
let i = 0;
|
|
6928
|
-
let p = 0;
|
|
6929
|
-
const len = str.length;
|
|
6930
|
-
for (; i < len; ++i) if (this.buffer !== void 0) if (!HEX[str.charCodeAt(i)]) {
|
|
6931
|
-
res += "%" + this.buffer;
|
|
6932
|
-
this.buffer = void 0;
|
|
6933
|
-
--i;
|
|
6934
|
-
} else {
|
|
6935
|
-
this.buffer += str[i];
|
|
6936
|
-
++p;
|
|
6937
|
-
if (this.buffer.length === 2) {
|
|
6938
|
-
res += String.fromCharCode(parseInt(this.buffer, 16));
|
|
6939
|
-
this.buffer = void 0;
|
|
6940
|
-
}
|
|
6941
|
-
}
|
|
6942
|
-
else if (str[i] === "%") {
|
|
6943
|
-
if (i > p) {
|
|
6944
|
-
res += str.substring(p, i);
|
|
6945
|
-
p = i;
|
|
6946
|
-
}
|
|
6947
|
-
this.buffer = "";
|
|
6948
|
-
++p;
|
|
6949
|
-
}
|
|
6950
|
-
if (p < len && this.buffer === void 0) res += str.substring(p);
|
|
6951
|
-
return res;
|
|
6952
|
-
};
|
|
6953
|
-
Decoder.prototype.reset = function() {
|
|
6954
|
-
this.buffer = void 0;
|
|
6955
|
-
};
|
|
6956
|
-
module.exports = Decoder;
|
|
6957
|
-
}));
|
|
6958
|
-
//#endregion
|
|
6959
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/types/urlencoded.js
|
|
6960
|
-
var require_urlencoded = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6961
|
-
const Decoder = require_Decoder();
|
|
6962
|
-
const decodeText = require_decodeText();
|
|
6963
|
-
const getLimit = require_getLimit();
|
|
6964
|
-
const RE_CHARSET = /^charset$/i;
|
|
6965
|
-
UrlEncoded.detect = /^application\/x-www-form-urlencoded/i;
|
|
6966
|
-
function UrlEncoded(boy, cfg) {
|
|
6967
|
-
const limits = cfg.limits;
|
|
6968
|
-
const parsedConType = cfg.parsedConType;
|
|
6969
|
-
this.boy = boy;
|
|
6970
|
-
this.fieldSizeLimit = getLimit(limits, "fieldSize", 1 * 1024 * 1024);
|
|
6971
|
-
this.fieldNameSizeLimit = getLimit(limits, "fieldNameSize", 100);
|
|
6972
|
-
this.fieldsLimit = getLimit(limits, "fields", Infinity);
|
|
6973
|
-
let charset;
|
|
6974
|
-
for (var i = 0, len = parsedConType.length; i < len; ++i) if (Array.isArray(parsedConType[i]) && RE_CHARSET.test(parsedConType[i][0])) {
|
|
6975
|
-
charset = parsedConType[i][1].toLowerCase();
|
|
6976
|
-
break;
|
|
6977
|
-
}
|
|
6978
|
-
if (charset === void 0) charset = cfg.defCharset || "utf8";
|
|
6979
|
-
this.decoder = new Decoder();
|
|
6980
|
-
this.charset = charset;
|
|
6981
|
-
this._fields = 0;
|
|
6982
|
-
this._state = "key";
|
|
6983
|
-
this._checkingBytes = true;
|
|
6984
|
-
this._bytesKey = 0;
|
|
6985
|
-
this._bytesVal = 0;
|
|
6986
|
-
this._key = "";
|
|
6987
|
-
this._val = "";
|
|
6988
|
-
this._keyTrunc = false;
|
|
6989
|
-
this._valTrunc = false;
|
|
6990
|
-
this._hitLimit = false;
|
|
6991
|
-
}
|
|
6992
|
-
UrlEncoded.prototype.write = function(data, cb) {
|
|
6993
|
-
if (this._fields === this.fieldsLimit) {
|
|
6994
|
-
if (!this.boy.hitFieldsLimit) {
|
|
6995
|
-
this.boy.hitFieldsLimit = true;
|
|
6996
|
-
this.boy.emit("fieldsLimit");
|
|
6997
|
-
}
|
|
6998
|
-
return cb();
|
|
6999
|
-
}
|
|
7000
|
-
let idxeq;
|
|
7001
|
-
let idxamp;
|
|
7002
|
-
let i;
|
|
7003
|
-
let p = 0;
|
|
7004
|
-
const len = data.length;
|
|
7005
|
-
while (p < len) if (this._state === "key") {
|
|
7006
|
-
idxeq = idxamp = void 0;
|
|
7007
|
-
for (i = p; i < len; ++i) {
|
|
7008
|
-
if (!this._checkingBytes) ++p;
|
|
7009
|
-
if (data[i] === 61) {
|
|
7010
|
-
idxeq = i;
|
|
7011
|
-
break;
|
|
7012
|
-
} else if (data[i] === 38) {
|
|
7013
|
-
idxamp = i;
|
|
7014
|
-
break;
|
|
7015
|
-
}
|
|
7016
|
-
if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) {
|
|
7017
|
-
this._hitLimit = true;
|
|
7018
|
-
break;
|
|
7019
|
-
} else if (this._checkingBytes) ++this._bytesKey;
|
|
7020
|
-
}
|
|
7021
|
-
if (idxeq !== void 0) {
|
|
7022
|
-
if (idxeq > p) this._key += this.decoder.write(data.toString("binary", p, idxeq));
|
|
7023
|
-
this._state = "val";
|
|
7024
|
-
this._hitLimit = false;
|
|
7025
|
-
this._checkingBytes = true;
|
|
7026
|
-
this._val = "";
|
|
7027
|
-
this._bytesVal = 0;
|
|
7028
|
-
this._valTrunc = false;
|
|
7029
|
-
this.decoder.reset();
|
|
7030
|
-
p = idxeq + 1;
|
|
7031
|
-
} else if (idxamp !== void 0) {
|
|
7032
|
-
++this._fields;
|
|
7033
|
-
let key;
|
|
7034
|
-
const keyTrunc = this._keyTrunc;
|
|
7035
|
-
if (idxamp > p) key = this._key += this.decoder.write(data.toString("binary", p, idxamp));
|
|
7036
|
-
else key = this._key;
|
|
7037
|
-
this._hitLimit = false;
|
|
7038
|
-
this._checkingBytes = true;
|
|
7039
|
-
this._key = "";
|
|
7040
|
-
this._bytesKey = 0;
|
|
7041
|
-
this._keyTrunc = false;
|
|
7042
|
-
this.decoder.reset();
|
|
7043
|
-
if (key.length) this.boy.emit("field", decodeText(key, "binary", this.charset), "", keyTrunc, false);
|
|
7044
|
-
p = idxamp + 1;
|
|
7045
|
-
if (this._fields === this.fieldsLimit) return cb();
|
|
7046
|
-
} else if (this._hitLimit) {
|
|
7047
|
-
if (i > p) this._key += this.decoder.write(data.toString("binary", p, i));
|
|
7048
|
-
p = i;
|
|
7049
|
-
if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) {
|
|
7050
|
-
this._checkingBytes = false;
|
|
7051
|
-
this._keyTrunc = true;
|
|
7052
|
-
}
|
|
7053
|
-
} else {
|
|
7054
|
-
if (p < len) this._key += this.decoder.write(data.toString("binary", p));
|
|
7055
|
-
p = len;
|
|
7056
|
-
}
|
|
7057
|
-
} else {
|
|
7058
|
-
idxamp = void 0;
|
|
7059
|
-
for (i = p; i < len; ++i) {
|
|
7060
|
-
if (!this._checkingBytes) ++p;
|
|
7061
|
-
if (data[i] === 38) {
|
|
7062
|
-
idxamp = i;
|
|
7063
|
-
break;
|
|
7064
|
-
}
|
|
7065
|
-
if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) {
|
|
7066
|
-
this._hitLimit = true;
|
|
7067
|
-
break;
|
|
7068
|
-
} else if (this._checkingBytes) ++this._bytesVal;
|
|
7069
|
-
}
|
|
7070
|
-
if (idxamp !== void 0) {
|
|
7071
|
-
++this._fields;
|
|
7072
|
-
if (idxamp > p) this._val += this.decoder.write(data.toString("binary", p, idxamp));
|
|
7073
|
-
this.boy.emit("field", decodeText(this._key, "binary", this.charset), decodeText(this._val, "binary", this.charset), this._keyTrunc, this._valTrunc);
|
|
7074
|
-
this._state = "key";
|
|
7075
|
-
this._hitLimit = false;
|
|
7076
|
-
this._checkingBytes = true;
|
|
7077
|
-
this._key = "";
|
|
7078
|
-
this._bytesKey = 0;
|
|
7079
|
-
this._keyTrunc = false;
|
|
7080
|
-
this.decoder.reset();
|
|
7081
|
-
p = idxamp + 1;
|
|
7082
|
-
if (this._fields === this.fieldsLimit) return cb();
|
|
7083
|
-
} else if (this._hitLimit) {
|
|
7084
|
-
if (i > p) this._val += this.decoder.write(data.toString("binary", p, i));
|
|
7085
|
-
p = i;
|
|
7086
|
-
if (this._val === "" && this.fieldSizeLimit === 0 || (this._bytesVal = this._val.length) === this.fieldSizeLimit) {
|
|
7087
|
-
this._checkingBytes = false;
|
|
7088
|
-
this._valTrunc = true;
|
|
7089
|
-
}
|
|
7090
|
-
} else {
|
|
7091
|
-
if (p < len) this._val += this.decoder.write(data.toString("binary", p));
|
|
7092
|
-
p = len;
|
|
7093
|
-
}
|
|
7094
|
-
}
|
|
7095
|
-
cb();
|
|
7096
|
-
};
|
|
7097
|
-
UrlEncoded.prototype.end = function() {
|
|
7098
|
-
if (this.boy._done) return;
|
|
7099
|
-
if (this._state === "key" && this._key.length > 0) this.boy.emit("field", decodeText(this._key, "binary", this.charset), "", this._keyTrunc, false);
|
|
7100
|
-
else if (this._state === "val") this.boy.emit("field", decodeText(this._key, "binary", this.charset), decodeText(this._val, "binary", this.charset), this._keyTrunc, this._valTrunc);
|
|
7101
|
-
this.boy._done = true;
|
|
7102
|
-
this.boy.emit("finish");
|
|
7103
|
-
};
|
|
7104
|
-
module.exports = UrlEncoded;
|
|
7105
|
-
}));
|
|
7106
|
-
//#endregion
|
|
7107
|
-
//#region ../../node_modules/.pnpm/@fastify+busboy@3.2.0/node_modules/@fastify/busboy/lib/main.js
|
|
7108
|
-
var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7109
|
-
const WritableStream = __require("node:stream").Writable;
|
|
7110
|
-
const { inherits } = __require("node:util");
|
|
7111
|
-
const Dicer = require_Dicer();
|
|
7112
|
-
const MultipartParser = require_multipart$1();
|
|
7113
|
-
const UrlencodedParser = require_urlencoded();
|
|
7114
|
-
const parseParams = require_parseParams();
|
|
7115
|
-
function Busboy(opts) {
|
|
7116
|
-
if (!(this instanceof Busboy)) return new Busboy(opts);
|
|
7117
|
-
if (typeof opts !== "object") throw new TypeError("Busboy expected an options-Object.");
|
|
7118
|
-
if (typeof opts.headers !== "object") throw new TypeError("Busboy expected an options-Object with headers-attribute.");
|
|
7119
|
-
if (typeof opts.headers["content-type"] !== "string") throw new TypeError("Missing Content-Type-header.");
|
|
7120
|
-
const { headers, ...streamOptions } = opts;
|
|
7121
|
-
this.opts = {
|
|
7122
|
-
autoDestroy: false,
|
|
7123
|
-
...streamOptions
|
|
7124
|
-
};
|
|
7125
|
-
WritableStream.call(this, this.opts);
|
|
7126
|
-
this._done = false;
|
|
7127
|
-
this._parser = this.getParserByHeaders(headers);
|
|
7128
|
-
this._finished = false;
|
|
7129
|
-
}
|
|
7130
|
-
inherits(Busboy, WritableStream);
|
|
7131
|
-
Busboy.prototype.emit = function(ev) {
|
|
7132
|
-
if (ev === "finish") {
|
|
7133
|
-
if (!this._done) {
|
|
7134
|
-
this._parser?.end();
|
|
7135
|
-
return;
|
|
7136
|
-
} else if (this._finished) return;
|
|
7137
|
-
this._finished = true;
|
|
7138
|
-
}
|
|
7139
|
-
WritableStream.prototype.emit.apply(this, arguments);
|
|
7140
|
-
};
|
|
7141
|
-
Busboy.prototype.getParserByHeaders = function(headers) {
|
|
7142
|
-
const parsed = parseParams(headers["content-type"]);
|
|
7143
|
-
const cfg = {
|
|
7144
|
-
defCharset: this.opts.defCharset,
|
|
7145
|
-
fileHwm: this.opts.fileHwm,
|
|
7146
|
-
headers,
|
|
7147
|
-
highWaterMark: this.opts.highWaterMark,
|
|
7148
|
-
isPartAFile: this.opts.isPartAFile,
|
|
7149
|
-
limits: this.opts.limits,
|
|
7150
|
-
parsedConType: parsed,
|
|
7151
|
-
preservePath: this.opts.preservePath
|
|
7152
|
-
};
|
|
7153
|
-
if (MultipartParser.detect.test(parsed[0])) return new MultipartParser(this, cfg);
|
|
7154
|
-
if (UrlencodedParser.detect.test(parsed[0])) return new UrlencodedParser(this, cfg);
|
|
7155
|
-
throw new Error("Unsupported Content-Type.");
|
|
7156
|
-
};
|
|
7157
|
-
Busboy.prototype._write = function(chunk, encoding, cb) {
|
|
7158
|
-
this._parser.write(chunk, cb);
|
|
7159
|
-
};
|
|
7160
|
-
module.exports = Busboy;
|
|
7161
|
-
module.exports.default = Busboy;
|
|
7162
|
-
module.exports.Busboy = Busboy;
|
|
7163
|
-
module.exports.Dicer = Dicer;
|
|
7164
|
-
}));
|
|
7165
|
-
//#endregion
|
|
7166
|
-
//#region ../../node_modules/.pnpm/fastify-plugin@5.1.0/node_modules/fastify-plugin/lib/getPluginName.js
|
|
7167
|
-
var require_getPluginName = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7168
|
-
const fpStackTracePattern = /at\s(?:.*\.)?plugin\s.*\n\s*(.*)/;
|
|
7169
|
-
const fileNamePattern = /(\w*(\.\w*)*)\..*/;
|
|
7170
|
-
module.exports = function getPluginName(fn) {
|
|
7171
|
-
if (fn.name.length > 0) return fn.name;
|
|
7172
|
-
const stackTraceLimit = Error.stackTraceLimit;
|
|
7173
|
-
Error.stackTraceLimit = 10;
|
|
7174
|
-
try {
|
|
7175
|
-
throw new Error("anonymous function");
|
|
7176
|
-
} catch (e) {
|
|
7177
|
-
Error.stackTraceLimit = stackTraceLimit;
|
|
7178
|
-
return extractPluginName(e.stack);
|
|
7179
|
-
}
|
|
7180
|
-
};
|
|
7181
|
-
function extractPluginName(stack) {
|
|
7182
|
-
const m = stack.match(fpStackTracePattern);
|
|
7183
|
-
return m ? m[1].split(/[/\\]/).slice(-1)[0].match(fileNamePattern)[1] : "anonymous";
|
|
7184
|
-
}
|
|
7185
|
-
module.exports.extractPluginName = extractPluginName;
|
|
7186
|
-
}));
|
|
7187
|
-
//#endregion
|
|
7188
|
-
//#region ../../node_modules/.pnpm/fastify-plugin@5.1.0/node_modules/fastify-plugin/lib/toCamelCase.js
|
|
7189
|
-
var require_toCamelCase = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7190
|
-
module.exports = function toCamelCase(name) {
|
|
7191
|
-
if (name[0] === "@") name = name.slice(1).replace("/", "-");
|
|
7192
|
-
return name.replace(/-(.)/g, function(match, g1) {
|
|
7193
|
-
return g1.toUpperCase();
|
|
7194
|
-
});
|
|
7195
|
-
};
|
|
7196
|
-
}));
|
|
7197
|
-
//#endregion
|
|
7198
|
-
//#region ../../node_modules/.pnpm/fastify-plugin@5.1.0/node_modules/fastify-plugin/plugin.js
|
|
7199
|
-
var require_plugin = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7200
|
-
const getPluginName = require_getPluginName();
|
|
7201
|
-
const toCamelCase = require_toCamelCase();
|
|
7202
|
-
let count = 0;
|
|
7203
|
-
function plugin(fn, options = {}) {
|
|
7204
|
-
let autoName = false;
|
|
7205
|
-
if (fn.default !== void 0) fn = fn.default;
|
|
7206
|
-
if (typeof fn !== "function") throw new TypeError(`fastify-plugin expects a function, instead got a '${typeof fn}'`);
|
|
7207
|
-
if (typeof options === "string") options = { fastify: options };
|
|
7208
|
-
if (typeof options !== "object" || Array.isArray(options) || options === null) throw new TypeError("The options object should be an object");
|
|
7209
|
-
if (options.fastify !== void 0 && typeof options.fastify !== "string") throw new TypeError(`fastify-plugin expects a version string, instead got '${typeof options.fastify}'`);
|
|
7210
|
-
if (!options.name) {
|
|
7211
|
-
autoName = true;
|
|
7212
|
-
options.name = getPluginName(fn) + "-auto-" + count++;
|
|
7213
|
-
}
|
|
7214
|
-
fn[Symbol.for("skip-override")] = options.encapsulate !== true;
|
|
7215
|
-
fn[Symbol.for("fastify.display-name")] = options.name;
|
|
7216
|
-
fn[Symbol.for("plugin-meta")] = options;
|
|
7217
|
-
if (!fn.default) fn.default = fn;
|
|
7218
|
-
const camelCase = toCamelCase(options.name);
|
|
7219
|
-
if (!autoName && !fn[camelCase]) fn[camelCase] = fn;
|
|
7220
|
-
return fn;
|
|
7221
|
-
}
|
|
7222
|
-
module.exports = plugin;
|
|
7223
|
-
module.exports.default = plugin;
|
|
7224
|
-
module.exports.fastifyPlugin = plugin;
|
|
7225
|
-
}));
|
|
7226
|
-
//#endregion
|
|
7227
|
-
//#region ../../node_modules/.pnpm/@fastify+multipart@10.0.0/node_modules/@fastify/multipart/lib/generateId.js
|
|
7228
|
-
var require_generateId = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7229
|
-
const HEX = [
|
|
7230
|
-
"00",
|
|
7231
|
-
"01",
|
|
7232
|
-
"02",
|
|
7233
|
-
"03",
|
|
7234
|
-
"04",
|
|
7235
|
-
"05",
|
|
7236
|
-
"06",
|
|
7237
|
-
"07",
|
|
7238
|
-
"08",
|
|
7239
|
-
"09",
|
|
7240
|
-
"0a",
|
|
7241
|
-
"0b",
|
|
7242
|
-
"0c",
|
|
7243
|
-
"0d",
|
|
7244
|
-
"0e",
|
|
7245
|
-
"0f",
|
|
7246
|
-
"10",
|
|
7247
|
-
"11",
|
|
7248
|
-
"12",
|
|
7249
|
-
"13",
|
|
7250
|
-
"14",
|
|
7251
|
-
"15",
|
|
7252
|
-
"16",
|
|
7253
|
-
"17",
|
|
7254
|
-
"18",
|
|
7255
|
-
"19",
|
|
7256
|
-
"1a",
|
|
7257
|
-
"1b",
|
|
7258
|
-
"1c",
|
|
7259
|
-
"1d",
|
|
7260
|
-
"1e",
|
|
7261
|
-
"1f",
|
|
7262
|
-
"20",
|
|
7263
|
-
"21",
|
|
7264
|
-
"22",
|
|
7265
|
-
"23",
|
|
7266
|
-
"24",
|
|
7267
|
-
"25",
|
|
7268
|
-
"26",
|
|
7269
|
-
"27",
|
|
7270
|
-
"28",
|
|
7271
|
-
"29",
|
|
7272
|
-
"2a",
|
|
7273
|
-
"2b",
|
|
7274
|
-
"2c",
|
|
7275
|
-
"2d",
|
|
7276
|
-
"2e",
|
|
7277
|
-
"2f",
|
|
7278
|
-
"30",
|
|
7279
|
-
"31",
|
|
7280
|
-
"32",
|
|
7281
|
-
"33",
|
|
7282
|
-
"34",
|
|
7283
|
-
"35",
|
|
7284
|
-
"36",
|
|
7285
|
-
"37",
|
|
7286
|
-
"38",
|
|
7287
|
-
"39",
|
|
7288
|
-
"3a",
|
|
7289
|
-
"3b",
|
|
7290
|
-
"3c",
|
|
7291
|
-
"3d",
|
|
7292
|
-
"3e",
|
|
7293
|
-
"3f",
|
|
7294
|
-
"40",
|
|
7295
|
-
"41",
|
|
7296
|
-
"42",
|
|
7297
|
-
"43",
|
|
7298
|
-
"44",
|
|
7299
|
-
"45",
|
|
7300
|
-
"46",
|
|
7301
|
-
"47",
|
|
7302
|
-
"48",
|
|
7303
|
-
"49",
|
|
7304
|
-
"4a",
|
|
7305
|
-
"4b",
|
|
7306
|
-
"4c",
|
|
7307
|
-
"4d",
|
|
7308
|
-
"4e",
|
|
7309
|
-
"4f",
|
|
7310
|
-
"50",
|
|
7311
|
-
"51",
|
|
7312
|
-
"52",
|
|
7313
|
-
"53",
|
|
7314
|
-
"54",
|
|
7315
|
-
"55",
|
|
7316
|
-
"56",
|
|
7317
|
-
"57",
|
|
7318
|
-
"58",
|
|
7319
|
-
"59",
|
|
7320
|
-
"5a",
|
|
7321
|
-
"5b",
|
|
7322
|
-
"5c",
|
|
7323
|
-
"5d",
|
|
7324
|
-
"5e",
|
|
7325
|
-
"5f",
|
|
7326
|
-
"60",
|
|
7327
|
-
"61",
|
|
7328
|
-
"62",
|
|
7329
|
-
"63",
|
|
7330
|
-
"64",
|
|
7331
|
-
"65",
|
|
7332
|
-
"66",
|
|
7333
|
-
"67",
|
|
7334
|
-
"68",
|
|
7335
|
-
"69",
|
|
7336
|
-
"6a",
|
|
7337
|
-
"6b",
|
|
7338
|
-
"6c",
|
|
7339
|
-
"6d",
|
|
7340
|
-
"6e",
|
|
7341
|
-
"6f",
|
|
7342
|
-
"70",
|
|
7343
|
-
"71",
|
|
7344
|
-
"72",
|
|
7345
|
-
"73",
|
|
7346
|
-
"74",
|
|
7347
|
-
"75",
|
|
7348
|
-
"76",
|
|
7349
|
-
"77",
|
|
7350
|
-
"78",
|
|
7351
|
-
"79",
|
|
7352
|
-
"7a",
|
|
7353
|
-
"7b",
|
|
7354
|
-
"7c",
|
|
7355
|
-
"7d",
|
|
7356
|
-
"7e",
|
|
7357
|
-
"7f",
|
|
7358
|
-
"80",
|
|
7359
|
-
"81",
|
|
7360
|
-
"82",
|
|
7361
|
-
"83",
|
|
7362
|
-
"84",
|
|
7363
|
-
"85",
|
|
7364
|
-
"86",
|
|
7365
|
-
"87",
|
|
7366
|
-
"88",
|
|
7367
|
-
"89",
|
|
7368
|
-
"8a",
|
|
7369
|
-
"8b",
|
|
7370
|
-
"8c",
|
|
7371
|
-
"8d",
|
|
7372
|
-
"8e",
|
|
7373
|
-
"8f",
|
|
7374
|
-
"90",
|
|
7375
|
-
"91",
|
|
7376
|
-
"92",
|
|
7377
|
-
"93",
|
|
7378
|
-
"94",
|
|
7379
|
-
"95",
|
|
7380
|
-
"96",
|
|
7381
|
-
"97",
|
|
7382
|
-
"98",
|
|
7383
|
-
"99",
|
|
7384
|
-
"9a",
|
|
7385
|
-
"9b",
|
|
7386
|
-
"9c",
|
|
7387
|
-
"9d",
|
|
7388
|
-
"9e",
|
|
7389
|
-
"9f",
|
|
7390
|
-
"a0",
|
|
7391
|
-
"a1",
|
|
7392
|
-
"a2",
|
|
7393
|
-
"a3",
|
|
7394
|
-
"a4",
|
|
7395
|
-
"a5",
|
|
7396
|
-
"a6",
|
|
7397
|
-
"a7",
|
|
7398
|
-
"a8",
|
|
7399
|
-
"a9",
|
|
7400
|
-
"aa",
|
|
7401
|
-
"ab",
|
|
7402
|
-
"ac",
|
|
7403
|
-
"ad",
|
|
7404
|
-
"ae",
|
|
7405
|
-
"af",
|
|
7406
|
-
"b0",
|
|
7407
|
-
"b1",
|
|
7408
|
-
"b2",
|
|
7409
|
-
"b3",
|
|
7410
|
-
"b4",
|
|
7411
|
-
"b5",
|
|
7412
|
-
"b6",
|
|
7413
|
-
"b7",
|
|
7414
|
-
"b8",
|
|
7415
|
-
"b9",
|
|
7416
|
-
"ba",
|
|
7417
|
-
"bb",
|
|
7418
|
-
"bc",
|
|
7419
|
-
"bd",
|
|
7420
|
-
"be",
|
|
7421
|
-
"bf",
|
|
7422
|
-
"c0",
|
|
7423
|
-
"c1",
|
|
7424
|
-
"c2",
|
|
7425
|
-
"c3",
|
|
7426
|
-
"c4",
|
|
7427
|
-
"c5",
|
|
7428
|
-
"c6",
|
|
7429
|
-
"c7",
|
|
7430
|
-
"c8",
|
|
7431
|
-
"c9",
|
|
7432
|
-
"ca",
|
|
7433
|
-
"cb",
|
|
7434
|
-
"cc",
|
|
7435
|
-
"cd",
|
|
7436
|
-
"ce",
|
|
7437
|
-
"cf",
|
|
7438
|
-
"d0",
|
|
7439
|
-
"d1",
|
|
7440
|
-
"d2",
|
|
7441
|
-
"d3",
|
|
7442
|
-
"d4",
|
|
7443
|
-
"d5",
|
|
7444
|
-
"d6",
|
|
7445
|
-
"d7",
|
|
7446
|
-
"d8",
|
|
7447
|
-
"d9",
|
|
7448
|
-
"da",
|
|
7449
|
-
"db",
|
|
7450
|
-
"dc",
|
|
7451
|
-
"dd",
|
|
7452
|
-
"de",
|
|
7453
|
-
"df",
|
|
7454
|
-
"e0",
|
|
7455
|
-
"e1",
|
|
7456
|
-
"e2",
|
|
7457
|
-
"e3",
|
|
7458
|
-
"e4",
|
|
7459
|
-
"e5",
|
|
7460
|
-
"e6",
|
|
7461
|
-
"e7",
|
|
7462
|
-
"e8",
|
|
7463
|
-
"e9",
|
|
7464
|
-
"ea",
|
|
7465
|
-
"eb",
|
|
7466
|
-
"ec",
|
|
7467
|
-
"ed",
|
|
7468
|
-
"ee",
|
|
7469
|
-
"ef",
|
|
7470
|
-
"f0",
|
|
7471
|
-
"f1",
|
|
7472
|
-
"f2",
|
|
7473
|
-
"f3",
|
|
7474
|
-
"f4",
|
|
7475
|
-
"f5",
|
|
7476
|
-
"f6",
|
|
7477
|
-
"f7",
|
|
7478
|
-
"f8",
|
|
7479
|
-
"f9",
|
|
7480
|
-
"fa",
|
|
7481
|
-
"fb",
|
|
7482
|
-
"fc",
|
|
7483
|
-
"fd",
|
|
7484
|
-
"fe",
|
|
7485
|
-
"ff"
|
|
7486
|
-
];
|
|
7487
|
-
const random = Math.random;
|
|
7488
|
-
function seed() {
|
|
7489
|
-
return HEX[255 * random() | 0] + HEX[255 * random() | 0] + HEX[255 * random() | 0] + HEX[255 * random() | 0] + HEX[255 * random() | 0] + HEX[255 * random() | 0] + HEX[255 * random() | 0];
|
|
7490
|
-
}
|
|
7491
|
-
module.exports.generateId = (function generateIdFn() {
|
|
7492
|
-
let num = 0;
|
|
7493
|
-
let str = seed();
|
|
7494
|
-
return function generateId() {
|
|
7495
|
-
return num === 255 ? (str = seed()) + HEX[num = 0] : str + HEX[++num];
|
|
7496
|
-
};
|
|
7497
|
-
})();
|
|
7498
|
-
}));
|
|
7499
|
-
//#endregion
|
|
7500
|
-
//#region ../../node_modules/.pnpm/@fastify+error@4.2.0/node_modules/@fastify/error/index.js
|
|
7501
|
-
var require_error = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7502
|
-
const { format } = __require("node:util");
|
|
7503
|
-
function toString() {
|
|
7504
|
-
return `${this.name} [${this.code}]: ${this.message}`;
|
|
7505
|
-
}
|
|
7506
|
-
const FastifyGenericErrorSymbol = Symbol.for("fastify-error-generic");
|
|
7507
|
-
function createError(code, message, statusCode = 500, Base = Error, captureStackTrace = createError.captureStackTrace) {
|
|
7508
|
-
const shouldCreateFastifyGenericError = code === FastifyGenericErrorSymbol;
|
|
7509
|
-
if (shouldCreateFastifyGenericError) code = "FST_ERR";
|
|
7510
|
-
if (!code) throw new Error("Fastify error code must not be empty");
|
|
7511
|
-
if (!message) throw new Error("Fastify error message must not be empty");
|
|
7512
|
-
code = code.toUpperCase();
|
|
7513
|
-
!statusCode && (statusCode = void 0);
|
|
7514
|
-
const FastifySpecificErrorSymbol = Symbol.for(`fastify-error ${code}`);
|
|
7515
|
-
function FastifyError(...args) {
|
|
7516
|
-
if (!new.target) return new FastifyError(...args);
|
|
7517
|
-
this.code = code;
|
|
7518
|
-
this.name = "FastifyError";
|
|
7519
|
-
this.statusCode = statusCode;
|
|
7520
|
-
const lastElement = args.length - 1;
|
|
7521
|
-
if (lastElement !== -1 && args[lastElement] && typeof args[lastElement] === "object" && "cause" in args[lastElement]) this.cause = args.pop().cause;
|
|
7522
|
-
this.message = format(message, ...args);
|
|
7523
|
-
Error.stackTraceLimit && captureStackTrace && Error.captureStackTrace(this, FastifyError);
|
|
7524
|
-
}
|
|
7525
|
-
FastifyError.prototype = Object.create(Base.prototype, {
|
|
7526
|
-
constructor: {
|
|
7527
|
-
value: FastifyError,
|
|
7528
|
-
enumerable: false,
|
|
7529
|
-
writable: true,
|
|
7530
|
-
configurable: true
|
|
7531
|
-
},
|
|
7532
|
-
[FastifyGenericErrorSymbol]: {
|
|
7533
|
-
value: true,
|
|
7534
|
-
enumerable: false,
|
|
7535
|
-
writable: false,
|
|
7536
|
-
configurable: false
|
|
7537
|
-
},
|
|
7538
|
-
[FastifySpecificErrorSymbol]: {
|
|
7539
|
-
value: true,
|
|
7540
|
-
enumerable: false,
|
|
7541
|
-
writable: false,
|
|
7542
|
-
configurable: false
|
|
7543
|
-
}
|
|
7544
|
-
});
|
|
7545
|
-
if (shouldCreateFastifyGenericError) Object.defineProperty(FastifyError, Symbol.hasInstance, {
|
|
7546
|
-
value(instance) {
|
|
7547
|
-
return instance && instance[FastifyGenericErrorSymbol];
|
|
7548
|
-
},
|
|
7549
|
-
configurable: false,
|
|
7550
|
-
writable: false,
|
|
7551
|
-
enumerable: false
|
|
7552
|
-
});
|
|
7553
|
-
else Object.defineProperty(FastifyError, Symbol.hasInstance, {
|
|
7554
|
-
value(instance) {
|
|
7555
|
-
return instance && instance[FastifySpecificErrorSymbol];
|
|
7556
|
-
},
|
|
7557
|
-
configurable: false,
|
|
7558
|
-
writable: false,
|
|
7559
|
-
enumerable: false
|
|
7560
|
-
});
|
|
7561
|
-
FastifyError.prototype[Symbol.toStringTag] = "Error";
|
|
7562
|
-
FastifyError.prototype.toString = toString;
|
|
7563
|
-
return FastifyError;
|
|
7564
|
-
}
|
|
7565
|
-
createError.captureStackTrace = true;
|
|
7566
|
-
const FastifyErrorConstructor = createError(FastifyGenericErrorSymbol, "Fastify Error", 500, Error);
|
|
7567
|
-
module.exports = createError;
|
|
7568
|
-
module.exports.FastifyError = FastifyErrorConstructor;
|
|
7569
|
-
module.exports.default = createError;
|
|
7570
|
-
module.exports.createError = createError;
|
|
7571
|
-
}));
|
|
7572
|
-
//#endregion
|
|
7573
|
-
//#region ../../node_modules/.pnpm/@fastify+multipart@10.0.0/node_modules/@fastify/multipart/lib/stream-consumer.js
|
|
7574
|
-
var require_stream_consumer = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7575
|
-
module.exports = function streamToNull(stream) {
|
|
7576
|
-
return new Promise((resolve, reject) => {
|
|
7577
|
-
stream.on("data", () => {});
|
|
7578
|
-
stream.on("close", () => {
|
|
7579
|
-
resolve();
|
|
7580
|
-
});
|
|
7581
|
-
stream.on("end", () => {
|
|
7582
|
-
resolve();
|
|
7583
|
-
});
|
|
7584
|
-
stream.on("error", (error) => {
|
|
7585
|
-
reject(error);
|
|
7586
|
-
});
|
|
7587
|
-
});
|
|
7588
|
-
};
|
|
7589
|
-
}));
|
|
7590
|
-
//#endregion
|
|
7591
|
-
//#region ../../node_modules/.pnpm/@fastify+deepmerge@3.2.1/node_modules/@fastify/deepmerge/index.js
|
|
7592
|
-
var require_deepmerge = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7593
|
-
const JSON_PROTO = Object.getPrototypeOf({});
|
|
7594
|
-
function defaultIsMergeableObjectFactory() {
|
|
7595
|
-
return function defaultIsMergeableObject(value) {
|
|
7596
|
-
return typeof value === "object" && value !== null && !(value instanceof RegExp) && !(value instanceof Date);
|
|
7597
|
-
};
|
|
7598
|
-
}
|
|
7599
|
-
function deepmergeConstructor(options) {
|
|
7600
|
-
function isNotPrototypeKey(value) {
|
|
7601
|
-
return value !== "constructor" && value !== "prototype" && value !== "__proto__";
|
|
7602
|
-
}
|
|
7603
|
-
function cloneArray(value) {
|
|
7604
|
-
let i = 0;
|
|
7605
|
-
const il = value.length;
|
|
7606
|
-
const result = new Array(il);
|
|
7607
|
-
for (; i < il; ++i) result[i] = clone(value[i]);
|
|
7608
|
-
return result;
|
|
7609
|
-
}
|
|
7610
|
-
function cloneObject(target) {
|
|
7611
|
-
const result = {};
|
|
7612
|
-
if (cloneProtoObject && Object.getPrototypeOf(target) !== JSON_PROTO) return cloneProtoObject(target);
|
|
7613
|
-
const targetKeys = getKeys(target);
|
|
7614
|
-
let i, il, key;
|
|
7615
|
-
for (i = 0, il = targetKeys.length; i < il; ++i) isNotPrototypeKey(key = targetKeys[i]) && (result[key] = clone(target[key]));
|
|
7616
|
-
return result;
|
|
7617
|
-
}
|
|
7618
|
-
function concatArrays(target, source) {
|
|
7619
|
-
const tl = target.length;
|
|
7620
|
-
const sl = source.length;
|
|
7621
|
-
let i = 0;
|
|
7622
|
-
const result = new Array(tl + sl);
|
|
7623
|
-
for (; i < tl; ++i) result[i] = clone(target[i]);
|
|
7624
|
-
for (i = 0; i < sl; ++i) result[i + tl] = clone(source[i]);
|
|
7625
|
-
return result;
|
|
7626
|
-
}
|
|
7627
|
-
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
7628
|
-
function getSymbolsAndKeys(value) {
|
|
7629
|
-
const result = Object.keys(value);
|
|
7630
|
-
const keys = Object.getOwnPropertySymbols(value);
|
|
7631
|
-
for (let i = 0, il = keys.length; i < il; ++i) propertyIsEnumerable.call(value, keys[i]) && result.push(keys[i]);
|
|
7632
|
-
return result;
|
|
7633
|
-
}
|
|
7634
|
-
const getKeys = options?.symbols ? getSymbolsAndKeys : Object.keys;
|
|
7635
|
-
const cloneProtoObject = typeof options?.cloneProtoObject === "function" ? options.cloneProtoObject : void 0;
|
|
7636
|
-
const isMergeableObject = typeof options?.isMergeableObject === "function" ? options.isMergeableObject : defaultIsMergeableObjectFactory();
|
|
7637
|
-
const onlyDefinedProperties = options?.onlyDefinedProperties === true;
|
|
7638
|
-
function isPrimitive(value) {
|
|
7639
|
-
return typeof value !== "object" || value === null;
|
|
7640
|
-
}
|
|
7641
|
-
const mergeArray = options && typeof options.mergeArray === "function" ? options.mergeArray({
|
|
7642
|
-
clone,
|
|
7643
|
-
deepmerge: _deepmerge,
|
|
7644
|
-
getKeys,
|
|
7645
|
-
isMergeableObject
|
|
7646
|
-
}) : concatArrays;
|
|
7647
|
-
function clone(entry) {
|
|
7648
|
-
return isMergeableObject(entry) ? Array.isArray(entry) ? cloneArray(entry) : cloneObject(entry) : entry;
|
|
7649
|
-
}
|
|
7650
|
-
function mergeObject(target, source) {
|
|
7651
|
-
const result = {};
|
|
7652
|
-
const targetKeys = getKeys(target);
|
|
7653
|
-
const sourceKeys = getKeys(source);
|
|
7654
|
-
let i, il, key;
|
|
7655
|
-
for (i = 0, il = targetKeys.length; i < il; ++i) isNotPrototypeKey(key = targetKeys[i]) && sourceKeys.indexOf(key) === -1 && (result[key] = clone(target[key]));
|
|
7656
|
-
for (i = 0, il = sourceKeys.length; i < il; ++i) {
|
|
7657
|
-
if (!isNotPrototypeKey(key = sourceKeys[i])) continue;
|
|
7658
|
-
if (key in target) {
|
|
7659
|
-
if (targetKeys.indexOf(key) !== -1) if (cloneProtoObject && isMergeableObject(source[key]) && Object.getPrototypeOf(source[key]) !== JSON_PROTO) result[key] = cloneProtoObject(source[key]);
|
|
7660
|
-
else result[key] = _deepmerge(target[key], source[key]);
|
|
7661
|
-
} else {
|
|
7662
|
-
if (onlyDefinedProperties && typeof source[key] === "undefined") continue;
|
|
7663
|
-
result[key] = clone(source[key]);
|
|
7664
|
-
}
|
|
7665
|
-
}
|
|
7666
|
-
return result;
|
|
7667
|
-
}
|
|
7668
|
-
function _deepmerge(target, source) {
|
|
7669
|
-
if (onlyDefinedProperties && typeof source === "undefined") return clone(target);
|
|
7670
|
-
const sourceIsArray = Array.isArray(source);
|
|
7671
|
-
const targetIsArray = Array.isArray(target);
|
|
7672
|
-
if (isPrimitive(source)) return source;
|
|
7673
|
-
else if (!isMergeableObject(target)) return clone(source);
|
|
7674
|
-
else if (sourceIsArray && targetIsArray) return mergeArray(target, source);
|
|
7675
|
-
else if (sourceIsArray !== targetIsArray) return clone(source);
|
|
7676
|
-
else return mergeObject(target, source);
|
|
7677
|
-
}
|
|
7678
|
-
function _deepmergeAll() {
|
|
7679
|
-
switch (arguments.length) {
|
|
7680
|
-
case 0: return {};
|
|
7681
|
-
case 1: return clone(arguments[0]);
|
|
7682
|
-
case 2: return _deepmerge(arguments[0], arguments[1]);
|
|
7683
|
-
}
|
|
7684
|
-
let result;
|
|
7685
|
-
for (let i = 0, il = arguments.length; i < il; ++i) result = _deepmerge(result, arguments[i]);
|
|
7686
|
-
return result;
|
|
7687
|
-
}
|
|
7688
|
-
return options?.all ? _deepmergeAll : _deepmerge;
|
|
7689
|
-
}
|
|
7690
|
-
module.exports = deepmergeConstructor;
|
|
7691
|
-
module.exports.default = deepmergeConstructor;
|
|
7692
|
-
module.exports.deepmerge = deepmergeConstructor;
|
|
7693
|
-
Object.defineProperty(module.exports, "isMergeableObject", { get: defaultIsMergeableObjectFactory });
|
|
7694
|
-
}));
|
|
7695
|
-
//#endregion
|
|
7696
|
-
//#region ../../node_modules/.pnpm/secure-json-parse@4.1.0/node_modules/secure-json-parse/index.js
|
|
7697
|
-
var require_secure_json_parse = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7698
|
-
const hasBuffer = typeof Buffer !== "undefined";
|
|
7699
|
-
const suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
|
|
7700
|
-
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
|
7701
|
-
/**
|
|
7702
|
-
* @description Internal parse function that parses JSON text with security checks.
|
|
7703
|
-
* @private
|
|
7704
|
-
* @param {string|Buffer} text - The JSON text string or Buffer to parse.
|
|
7705
|
-
* @param {Function} [reviver] - The JSON.parse() optional reviver argument.
|
|
7706
|
-
* @param {import('./types').ParseOptions} [options] - Optional configuration object.
|
|
7707
|
-
* @returns {*} The parsed object.
|
|
7708
|
-
* @throws {SyntaxError} If a forbidden prototype property is found and `options.protoAction` or
|
|
7709
|
-
* `options.constructorAction` is `'error'`.
|
|
7710
|
-
*/
|
|
7711
|
-
function _parse(text, reviver, options) {
|
|
7712
|
-
if (options == null) {
|
|
7713
|
-
if (reviver !== null && typeof reviver === "object") {
|
|
7714
|
-
options = reviver;
|
|
7715
|
-
reviver = void 0;
|
|
7716
|
-
}
|
|
7717
|
-
}
|
|
7718
|
-
if (hasBuffer && Buffer.isBuffer(text)) text = text.toString();
|
|
7719
|
-
if (text && text.charCodeAt(0) === 65279) text = text.slice(1);
|
|
7720
|
-
const obj = JSON.parse(text, reviver);
|
|
7721
|
-
if (obj === null || typeof obj !== "object") return obj;
|
|
7722
|
-
const protoAction = options && options.protoAction || "error";
|
|
7723
|
-
const constructorAction = options && options.constructorAction || "error";
|
|
7724
|
-
if (protoAction === "ignore" && constructorAction === "ignore") return obj;
|
|
7725
|
-
if (protoAction !== "ignore" && constructorAction !== "ignore") {
|
|
7726
|
-
if (suspectProtoRx.test(text) === false && suspectConstructorRx.test(text) === false) return obj;
|
|
7727
|
-
} else if (protoAction !== "ignore" && constructorAction === "ignore") {
|
|
7728
|
-
if (suspectProtoRx.test(text) === false) return obj;
|
|
7729
|
-
} else if (suspectConstructorRx.test(text) === false) return obj;
|
|
7730
|
-
return filter(obj, {
|
|
7731
|
-
protoAction,
|
|
7732
|
-
constructorAction,
|
|
7733
|
-
safe: options && options.safe
|
|
7734
|
-
});
|
|
7735
|
-
}
|
|
7736
|
-
/**
|
|
7737
|
-
* @description Scans and filters an object for forbidden prototype properties.
|
|
7738
|
-
* @param {Object} obj - The object being scanned.
|
|
7739
|
-
* @param {import('./types').ParseOptions} [options] - Optional configuration object.
|
|
7740
|
-
* @returns {Object|null} The filtered object, or `null` if safe mode is enabled and issues are found.
|
|
7741
|
-
* @throws {SyntaxError} If a forbidden prototype property is found and `options.protoAction` or
|
|
7742
|
-
* `options.constructorAction` is `'error'`.
|
|
7743
|
-
*/
|
|
7744
|
-
function filter(obj, { protoAction = "error", constructorAction = "error", safe } = {}) {
|
|
7745
|
-
let next = [obj];
|
|
7746
|
-
while (next.length) {
|
|
7747
|
-
const nodes = next;
|
|
7748
|
-
next = [];
|
|
7749
|
-
for (const node of nodes) {
|
|
7750
|
-
if (protoAction !== "ignore" && Object.prototype.hasOwnProperty.call(node, "__proto__")) {
|
|
7751
|
-
if (safe === true) return null;
|
|
7752
|
-
else if (protoAction === "error") throw new SyntaxError("Object contains forbidden prototype property");
|
|
7753
|
-
delete node.__proto__;
|
|
7754
|
-
}
|
|
7755
|
-
if (constructorAction !== "ignore" && Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
7756
|
-
if (safe === true) return null;
|
|
7757
|
-
else if (constructorAction === "error") throw new SyntaxError("Object contains forbidden prototype property");
|
|
7758
|
-
delete node.constructor;
|
|
7759
|
-
}
|
|
7760
|
-
for (const key in node) {
|
|
7761
|
-
const value = node[key];
|
|
7762
|
-
if (value && typeof value === "object") next.push(value);
|
|
7763
|
-
}
|
|
7764
|
-
}
|
|
7765
|
-
}
|
|
7766
|
-
return obj;
|
|
7767
|
-
}
|
|
7768
|
-
/**
|
|
7769
|
-
* @description Parses a given JSON-formatted text into an object.
|
|
7770
|
-
* @param {string|Buffer} text - The JSON text string or Buffer to parse.
|
|
7771
|
-
* @param {Function} [reviver] - The `JSON.parse()` optional reviver argument, or options object.
|
|
7772
|
-
* @param {import('./types').ParseOptions} [options] - Optional configuration object.
|
|
7773
|
-
* @returns {*} The parsed object.
|
|
7774
|
-
* @throws {SyntaxError} If the JSON text is malformed or contains forbidden prototype properties
|
|
7775
|
-
* when `options.protoAction` or `options.constructorAction` is `'error'`.
|
|
7776
|
-
*/
|
|
7777
|
-
function parse(text, reviver, options) {
|
|
7778
|
-
const { stackTraceLimit } = Error;
|
|
7779
|
-
Error.stackTraceLimit = 0;
|
|
7780
|
-
try {
|
|
7781
|
-
return _parse(text, reviver, options);
|
|
7782
|
-
} finally {
|
|
7783
|
-
Error.stackTraceLimit = stackTraceLimit;
|
|
7784
|
-
}
|
|
7785
|
-
}
|
|
7786
|
-
/**
|
|
7787
|
-
* @description Safely parses a given JSON-formatted text into an object.
|
|
7788
|
-
* @param {string|Buffer} text - The JSON text string or Buffer to parse.
|
|
7789
|
-
* @param {Function} [reviver] - The `JSON.parse()` optional reviver argument.
|
|
7790
|
-
* @returns {*|null|undefined} The parsed object, `null` if security issues found, or `undefined` on parse error.
|
|
7791
|
-
*/
|
|
7792
|
-
function safeParse(text, reviver) {
|
|
7793
|
-
const { stackTraceLimit } = Error;
|
|
7794
|
-
Error.stackTraceLimit = 0;
|
|
7795
|
-
try {
|
|
7796
|
-
return _parse(text, reviver, { safe: true });
|
|
7797
|
-
} catch {
|
|
7798
|
-
return;
|
|
7799
|
-
} finally {
|
|
7800
|
-
Error.stackTraceLimit = stackTraceLimit;
|
|
7801
|
-
}
|
|
7802
|
-
}
|
|
7803
|
-
module.exports = parse;
|
|
7804
|
-
module.exports.default = parse;
|
|
7805
|
-
module.exports.parse = parse;
|
|
7806
|
-
module.exports.safeParse = safeParse;
|
|
7807
|
-
module.exports.scan = filter;
|
|
7808
|
-
}));
|
|
7809
|
-
//#endregion
|
|
7810
|
-
//#region ../server/dist/app-BcKNAbK-.mjs
|
|
7811
|
-
var import_multipart = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
7812
|
-
const Busboy = require_main();
|
|
7813
|
-
const os = __require("node:os");
|
|
7814
|
-
const fp = require_plugin();
|
|
7815
|
-
const { createWriteStream: createWriteStream$1 } = __require("node:fs");
|
|
7816
|
-
const { unlink } = __require("node:fs/promises");
|
|
7817
|
-
const path = __require("node:path");
|
|
7818
|
-
const { generateId } = require_generateId();
|
|
7819
|
-
const createError = require_error();
|
|
7820
|
-
const streamToNull = require_stream_consumer();
|
|
7821
|
-
const deepmergeAll = require_deepmerge()({ all: true });
|
|
7822
|
-
const { PassThrough, Readable } = __require("node:stream");
|
|
7823
|
-
const { pipeline: pump } = __require("node:stream/promises");
|
|
7824
|
-
const secureJSON = require_secure_json_parse();
|
|
7825
|
-
const kMultipart = Symbol("multipart");
|
|
7826
|
-
const kMultipartHandler = Symbol("multipartHandler");
|
|
7827
|
-
const kSavedRequestFilesResult = Symbol("savedRequestFilesResult");
|
|
7828
|
-
const PartsLimitError = createError("FST_PARTS_LIMIT", "reach parts limit", 413);
|
|
7829
|
-
const FilesLimitError = createError("FST_FILES_LIMIT", "reach files limit", 413);
|
|
7830
|
-
const FieldsLimitError = createError("FST_FIELDS_LIMIT", "reach fields limit", 413);
|
|
7831
|
-
const RequestFileTooLargeError = createError("FST_REQ_FILE_TOO_LARGE", "request file too large", 413);
|
|
7832
|
-
const PrototypeViolationError = createError("FST_PROTO_VIOLATION", "prototype property is not allowed as field name", 400);
|
|
7833
|
-
const InvalidMultipartContentTypeError = createError("FST_INVALID_MULTIPART_CONTENT_TYPE", "the request is not multipart", 406);
|
|
7834
|
-
const InvalidJSONFieldError = createError("FST_INVALID_JSON_FIELD_ERROR", "a request field is not a valid JSON as declared by its Content-Type", 406);
|
|
7835
|
-
const FileBufferNotFoundError = createError("FST_FILE_BUFFER_NOT_FOUND", "the file buffer was not found", 500);
|
|
7836
|
-
const NoFormData = createError("FST_NO_FORM_DATA", "FormData is not available", 500);
|
|
7837
|
-
function setMultipart(req, _payload, done) {
|
|
7838
|
-
req[kMultipart] = true;
|
|
7839
|
-
done();
|
|
7840
|
-
}
|
|
7841
|
-
function busboy(options) {
|
|
7842
|
-
try {
|
|
7843
|
-
return new Busboy(options);
|
|
7844
|
-
} catch (error) {
|
|
7845
|
-
const errorEmitter = new PassThrough();
|
|
7846
|
-
process.nextTick(function() {
|
|
7847
|
-
errorEmitter.emit("error", error);
|
|
7848
|
-
});
|
|
7849
|
-
return errorEmitter;
|
|
7850
|
-
}
|
|
7851
|
-
}
|
|
7852
|
-
function fastifyMultipart(fastify, options, done) {
|
|
7853
|
-
options.limits = {
|
|
7854
|
-
...options.limits,
|
|
7855
|
-
parts: options.limits?.parts || 1e3,
|
|
7856
|
-
fileSize: options.limits?.fileSize || fastify.initialConfig.bodyLimit
|
|
7857
|
-
};
|
|
7858
|
-
const attachFieldsToBody = options.attachFieldsToBody;
|
|
7859
|
-
if (attachFieldsToBody === true || attachFieldsToBody === "keyValues") {
|
|
7860
|
-
if (typeof options.sharedSchemaId === "string" && attachFieldsToBody === true) fastify.addSchema({
|
|
7861
|
-
$id: options.sharedSchemaId,
|
|
7862
|
-
type: "object",
|
|
7863
|
-
properties: {
|
|
7864
|
-
fieldname: { type: "string" },
|
|
7865
|
-
encoding: { type: "string" },
|
|
7866
|
-
filename: { type: "string" },
|
|
7867
|
-
mimetype: { type: "string" }
|
|
7868
|
-
}
|
|
7869
|
-
});
|
|
7870
|
-
fastify.addHook("preValidation", async function(req) {
|
|
7871
|
-
if (!req.isMultipart()) return;
|
|
7872
|
-
for await (const part of req.parts(req.routeOptions.config.multipartOptions)) {
|
|
7873
|
-
req.body = part.fields;
|
|
7874
|
-
if (part.file) if (options.onFile) await options.onFile.call(req, part);
|
|
7875
|
-
else await part.toBuffer();
|
|
7876
|
-
}
|
|
7877
|
-
if (attachFieldsToBody === "keyValues") {
|
|
7878
|
-
const body = {};
|
|
7879
|
-
if (req.body) {
|
|
7880
|
-
const reqBodyKeys = Object.keys(req.body);
|
|
7881
|
-
for (let i = 0; i < reqBodyKeys.length; ++i) {
|
|
7882
|
-
const key = reqBodyKeys[i];
|
|
7883
|
-
const field = req.body[key];
|
|
7884
|
-
if (field.value !== void 0) body[key] = field.value;
|
|
7885
|
-
else if (field._buf) body[key] = field._buf;
|
|
7886
|
-
else if (Array.isArray(field)) {
|
|
7887
|
-
const items = [];
|
|
7888
|
-
for (let i = 0; i < field.length; ++i) {
|
|
7889
|
-
const item = field[i];
|
|
7890
|
-
if (item.value !== void 0) items.push(item.value);
|
|
7891
|
-
else if (item._buf) items.push(item._buf);
|
|
7892
|
-
}
|
|
7893
|
-
if (items.length) body[key] = items;
|
|
7894
|
-
}
|
|
7895
|
-
}
|
|
7896
|
-
}
|
|
7897
|
-
req.body = body;
|
|
7898
|
-
}
|
|
7899
|
-
});
|
|
7900
|
-
/* istanbul ignore next */
|
|
7901
|
-
if (globalThis.FormData && !fastify.hasRequestDecorator("formData")) fastify.decorateRequest("formData", async function() {
|
|
7902
|
-
const formData = new FormData();
|
|
7903
|
-
for (const key in this.body) {
|
|
7904
|
-
const value = this.body[key];
|
|
7905
|
-
if (Array.isArray(value)) for (const item of value) await append(key, item);
|
|
7906
|
-
else await append(key, value);
|
|
7907
|
-
}
|
|
7908
|
-
async function append(key, entry) {
|
|
7909
|
-
/* c8 ignore next: Buffer.isBuffer is not covered and causing `npm test` to fail */
|
|
7910
|
-
if (entry.type === "file" || attachFieldsToBody === "keyValues" && Buffer.isBuffer(entry)) formData.append(key, new Blob([await entry.toBuffer()], { type: entry.mimetype }), entry.filename);
|
|
7911
|
-
else formData.append(key, entry.value);
|
|
7912
|
-
}
|
|
7913
|
-
return formData;
|
|
7914
|
-
});
|
|
7915
|
-
}
|
|
7916
|
-
/* istanbul ignore next */
|
|
7917
|
-
if (!fastify.hasRequestDecorator("formData")) fastify.decorateRequest("formData", async function() {
|
|
7918
|
-
/* c8 ignore next: Next line is not covered and causing `npm test` to fail */
|
|
7919
|
-
throw new NoFormData();
|
|
7920
|
-
});
|
|
7921
|
-
const defaultThrowFileSizeLimit = typeof options.throwFileSizeLimit === "boolean" ? options.throwFileSizeLimit : true;
|
|
7922
|
-
fastify.decorate("multipartErrors", {
|
|
7923
|
-
PartsLimitError,
|
|
7924
|
-
FilesLimitError,
|
|
7925
|
-
FieldsLimitError,
|
|
7926
|
-
PrototypeViolationError,
|
|
7927
|
-
InvalidMultipartContentTypeError,
|
|
7928
|
-
RequestFileTooLargeError,
|
|
7929
|
-
FileBufferNotFoundError
|
|
7930
|
-
});
|
|
7931
|
-
fastify.addContentTypeParser("multipart/form-data", setMultipart);
|
|
7932
|
-
fastify.decorateRequest(kMultipart, false);
|
|
7933
|
-
fastify.decorateRequest(kMultipartHandler, handleMultipart);
|
|
7934
|
-
fastify.decorateRequest(kSavedRequestFilesResult, null);
|
|
7935
|
-
fastify.decorateRequest("parts", getMultipartIterator);
|
|
7936
|
-
fastify.decorateRequest("isMultipart", isMultipart);
|
|
7937
|
-
fastify.decorateRequest("tmpUploads", null);
|
|
7938
|
-
fastify.decorateRequest("savedRequestFiles", null);
|
|
7939
|
-
fastify.decorateRequest("file", getMultipartFile);
|
|
7940
|
-
fastify.decorateRequest("files", getMultipartFiles);
|
|
7941
|
-
fastify.decorateRequest("saveRequestFiles", saveRequestFiles);
|
|
7942
|
-
fastify.decorateRequest("cleanRequestFiles", cleanRequestFiles);
|
|
7943
|
-
fastify.addHook("onResponse", async (request) => {
|
|
7944
|
-
await request.cleanRequestFiles();
|
|
7945
|
-
});
|
|
7946
|
-
function isMultipart() {
|
|
7947
|
-
return this[kMultipart];
|
|
7948
|
-
}
|
|
7949
|
-
function handleMultipart(opts = {}) {
|
|
7950
|
-
if (!this.isMultipart()) throw new InvalidMultipartContentTypeError();
|
|
7951
|
-
this.log.debug("starting multipart parsing");
|
|
7952
|
-
let values = [];
|
|
7953
|
-
let pendingHandler = null;
|
|
7954
|
-
const ch = (val) => {
|
|
7955
|
-
if (pendingHandler) {
|
|
7956
|
-
pendingHandler(val);
|
|
7957
|
-
pendingHandler = null;
|
|
7958
|
-
} else values.push(val);
|
|
7959
|
-
};
|
|
7960
|
-
const handle = (handler) => {
|
|
7961
|
-
if (values.length > 0) {
|
|
7962
|
-
const value = values[0];
|
|
7963
|
-
values = values.slice(1);
|
|
7964
|
-
handler(value);
|
|
7965
|
-
} else pendingHandler = handler;
|
|
7966
|
-
};
|
|
7967
|
-
const parts = () => {
|
|
7968
|
-
return new Promise((resolve, reject) => {
|
|
7969
|
-
handle((val) => {
|
|
7970
|
-
if (val instanceof Error) if (val.message === "Unexpected end of multipart data") resolve(null);
|
|
7971
|
-
else reject(val);
|
|
7972
|
-
else resolve(val);
|
|
7973
|
-
});
|
|
7974
|
-
});
|
|
7975
|
-
};
|
|
7976
|
-
const body = {};
|
|
7977
|
-
let lastError = null;
|
|
7978
|
-
let currentFile = null;
|
|
7979
|
-
const request = this.raw;
|
|
7980
|
-
const busboyOptions = deepmergeAll({ headers: request.headers }, options, opts);
|
|
7981
|
-
this.log.trace({ busboyOptions }, "Providing options to busboy");
|
|
7982
|
-
const bb = busboy(busboyOptions);
|
|
7983
|
-
request.on("close", cleanup);
|
|
7984
|
-
request.on("error", cleanup);
|
|
7985
|
-
bb.on("field", onField).on("file", onFile).on("end", cleanup).on("finish", cleanup).on("close", cleanup).on("error", cleanup);
|
|
7986
|
-
bb.on("partsLimit", function() {
|
|
7987
|
-
const err = new PartsLimitError();
|
|
7988
|
-
onError(err);
|
|
7989
|
-
process.nextTick(() => cleanup(err));
|
|
7990
|
-
});
|
|
7991
|
-
bb.on("filesLimit", function() {
|
|
7992
|
-
const err = new FilesLimitError();
|
|
7993
|
-
onError(err);
|
|
7994
|
-
process.nextTick(() => cleanup(err));
|
|
7995
|
-
});
|
|
7996
|
-
bb.on("fieldsLimit", function() {
|
|
7997
|
-
const err = new FieldsLimitError();
|
|
7998
|
-
onError(err);
|
|
7999
|
-
process.nextTick(() => cleanup(err));
|
|
8000
|
-
});
|
|
8001
|
-
request.pipe(bb);
|
|
8002
|
-
function onField(name, fieldValue, fieldnameTruncated, valueTruncated, encoding, contentType) {
|
|
8003
|
-
if (name in Object.prototype) {
|
|
8004
|
-
onError(new PrototypeViolationError());
|
|
8005
|
-
return;
|
|
8006
|
-
}
|
|
8007
|
-
if (contentType.startsWith("application/json")) {
|
|
8008
|
-
if (valueTruncated) {
|
|
8009
|
-
onError(new InvalidJSONFieldError());
|
|
8010
|
-
return;
|
|
8011
|
-
}
|
|
8012
|
-
try {
|
|
8013
|
-
fieldValue = secureJSON.parse(fieldValue);
|
|
8014
|
-
contentType = "application/json";
|
|
8015
|
-
} catch {
|
|
8016
|
-
onError(new InvalidJSONFieldError());
|
|
8017
|
-
return;
|
|
8018
|
-
}
|
|
8019
|
-
}
|
|
8020
|
-
const value = {
|
|
8021
|
-
type: "field",
|
|
8022
|
-
fieldname: name,
|
|
8023
|
-
mimetype: contentType,
|
|
8024
|
-
encoding,
|
|
8025
|
-
value: fieldValue,
|
|
8026
|
-
fieldnameTruncated,
|
|
8027
|
-
valueTruncated,
|
|
8028
|
-
fields: body
|
|
8029
|
-
};
|
|
8030
|
-
if (body[name] === void 0) body[name] = value;
|
|
8031
|
-
else if (Array.isArray(body[name])) body[name].push(value);
|
|
8032
|
-
else body[name] = [body[name], value];
|
|
8033
|
-
ch(value);
|
|
8034
|
-
}
|
|
8035
|
-
function onFile(name, file, filename, encoding, mimetype) {
|
|
8036
|
-
if (name in Object.prototype) {
|
|
8037
|
-
streamToNull(file).catch(() => {});
|
|
8038
|
-
onError(new PrototypeViolationError());
|
|
8039
|
-
return;
|
|
8040
|
-
}
|
|
8041
|
-
const throwFileSizeLimit = typeof opts.throwFileSizeLimit === "boolean" ? opts.throwFileSizeLimit : defaultThrowFileSizeLimit;
|
|
8042
|
-
const value = {
|
|
8043
|
-
type: "file",
|
|
8044
|
-
fieldname: name,
|
|
8045
|
-
filename,
|
|
8046
|
-
encoding,
|
|
8047
|
-
mimetype,
|
|
8048
|
-
file,
|
|
8049
|
-
fields: body,
|
|
8050
|
-
_buf: null,
|
|
8051
|
-
async toBuffer() {
|
|
8052
|
-
if (this._buf) return this._buf;
|
|
8053
|
-
const fileChunks = [];
|
|
8054
|
-
let err;
|
|
8055
|
-
for await (const chunk of this.file) {
|
|
8056
|
-
fileChunks.push(chunk);
|
|
8057
|
-
if (throwFileSizeLimit && this.file.truncated) {
|
|
8058
|
-
err = new RequestFileTooLargeError();
|
|
8059
|
-
err.part = this;
|
|
8060
|
-
onError(err);
|
|
8061
|
-
fileChunks.length = 0;
|
|
8062
|
-
}
|
|
8063
|
-
}
|
|
8064
|
-
if (err) throw err;
|
|
8065
|
-
this._buf = Buffer.concat(fileChunks);
|
|
8066
|
-
return this._buf;
|
|
8067
|
-
}
|
|
8068
|
-
};
|
|
8069
|
-
file.on("error", function(err) {
|
|
8070
|
-
if (err.message && err.message.includes("terminated early")) onError(err);
|
|
8071
|
-
});
|
|
8072
|
-
if (throwFileSizeLimit) file.on("limit", function() {
|
|
8073
|
-
const err = new RequestFileTooLargeError();
|
|
8074
|
-
err.part = value;
|
|
8075
|
-
onError(err);
|
|
8076
|
-
});
|
|
8077
|
-
if (body[name] === void 0) body[name] = value;
|
|
8078
|
-
else if (Array.isArray(body[name])) body[name].push(value);
|
|
8079
|
-
else body[name] = [body[name], value];
|
|
8080
|
-
currentFile = file;
|
|
8081
|
-
ch(value);
|
|
8082
|
-
}
|
|
8083
|
-
function onError(err) {
|
|
8084
|
-
lastError = err;
|
|
8085
|
-
currentFile = null;
|
|
8086
|
-
}
|
|
8087
|
-
function cleanup(err) {
|
|
8088
|
-
request.unpipe(bb);
|
|
8089
|
-
if ((err || request.aborted) && currentFile) {
|
|
8090
|
-
currentFile.destroy();
|
|
8091
|
-
currentFile = null;
|
|
8092
|
-
}
|
|
8093
|
-
ch(err || lastError || null);
|
|
8094
|
-
}
|
|
8095
|
-
return parts;
|
|
8096
|
-
}
|
|
8097
|
-
async function saveRequestFiles(options) {
|
|
8098
|
-
if (this[kSavedRequestFilesResult]) return this[kSavedRequestFilesResult];
|
|
8099
|
-
let parts;
|
|
8100
|
-
let values = {};
|
|
8101
|
-
if (attachFieldsToBody === true || attachFieldsToBody === "keyValues") {
|
|
8102
|
-
parts = this.body ? filesFromFields.call(this, this.body) : [];
|
|
8103
|
-
values = this.body || {};
|
|
8104
|
-
} else parts = this.parts(options);
|
|
8105
|
-
this.savedRequestFiles = [];
|
|
8106
|
-
const tmpdir = options?.tmpdir || os.tmpdir();
|
|
8107
|
-
this.tmpUploads = [];
|
|
8108
|
-
let i = 0;
|
|
8109
|
-
for await (const part of parts) {
|
|
8110
|
-
values = part.fields;
|
|
8111
|
-
if (!part.file) continue;
|
|
8112
|
-
const filepath = path.join(tmpdir, generateId() + path.extname(part.filename || "file" + i++));
|
|
8113
|
-
const target = createWriteStream$1(filepath);
|
|
8114
|
-
try {
|
|
8115
|
-
this.tmpUploads.push(filepath);
|
|
8116
|
-
await pump(part.file, target);
|
|
8117
|
-
this.savedRequestFiles.push({
|
|
8118
|
-
...part,
|
|
8119
|
-
filepath
|
|
8120
|
-
});
|
|
8121
|
-
} catch (err) {
|
|
8122
|
-
target.destroy();
|
|
8123
|
-
await this.cleanRequestFiles();
|
|
8124
|
-
this.log.error({ err }, "save request file");
|
|
8125
|
-
throw err;
|
|
8126
|
-
}
|
|
8127
|
-
}
|
|
8128
|
-
this[kSavedRequestFilesResult] = {
|
|
8129
|
-
files: this.savedRequestFiles,
|
|
8130
|
-
values
|
|
8131
|
-
};
|
|
8132
|
-
return this[kSavedRequestFilesResult];
|
|
8133
|
-
}
|
|
8134
|
-
function* filesFromFields(container) {
|
|
8135
|
-
try {
|
|
8136
|
-
const fields = Array.isArray(container) ? container : Object.values(container);
|
|
8137
|
-
for (let i = 0; i < fields.length; ++i) {
|
|
8138
|
-
const field = fields[i];
|
|
8139
|
-
if (Array.isArray(field)) for (const subField of filesFromFields.call(this, field)) yield subField;
|
|
8140
|
-
if (!field.file) continue;
|
|
8141
|
-
if (!field._buf) throw new FileBufferNotFoundError();
|
|
8142
|
-
field.file = Readable.from(field._buf);
|
|
8143
|
-
yield field;
|
|
8144
|
-
}
|
|
8145
|
-
} catch (err) {
|
|
8146
|
-
this.log.error({ err }, "save request file failed");
|
|
8147
|
-
throw err;
|
|
8148
|
-
}
|
|
8149
|
-
}
|
|
8150
|
-
async function cleanRequestFiles() {
|
|
8151
|
-
if (!this.tmpUploads) return;
|
|
8152
|
-
for (let i = 0; i < this.tmpUploads.length; ++i) {
|
|
8153
|
-
const filepath = this.tmpUploads[i];
|
|
8154
|
-
try {
|
|
8155
|
-
await unlink(filepath);
|
|
8156
|
-
} /* c8 ignore start */catch (error) {
|
|
8157
|
-
this.log.error(error, "Could not delete file");
|
|
8158
|
-
}
|
|
8159
|
-
}
|
|
8160
|
-
}
|
|
8161
|
-
async function getMultipartFile(options) {
|
|
8162
|
-
const parts = this[kMultipartHandler](options);
|
|
8163
|
-
let part;
|
|
8164
|
-
while ((part = await parts()) != null) if (part.file) return part;
|
|
8165
|
-
}
|
|
8166
|
-
async function* getMultipartFiles(options) {
|
|
8167
|
-
const parts = this[kMultipartHandler](options);
|
|
8168
|
-
let part;
|
|
8169
|
-
while ((part = await parts()) != null) if (part.file) yield part;
|
|
8170
|
-
}
|
|
8171
|
-
async function* getMultipartIterator(options) {
|
|
8172
|
-
const parts = this[kMultipartHandler](options);
|
|
8173
|
-
let part;
|
|
8174
|
-
while ((part = await parts()) != null) yield part;
|
|
8175
|
-
}
|
|
8176
|
-
done();
|
|
8177
|
-
}
|
|
8178
|
-
/**
|
|
8179
|
-
* Adds a new type `isFile` to help @fastify/swagger generate the correct schema.
|
|
8180
|
-
*/
|
|
8181
|
-
function ajvFilePlugin(ajv) {
|
|
8182
|
-
return ajv.addKeyword({
|
|
8183
|
-
keyword: "isFile",
|
|
8184
|
-
compile: (_schema, parent) => {
|
|
8185
|
-
parent.type = "string";
|
|
8186
|
-
parent.format = "binary";
|
|
8187
|
-
delete parent.isFile;
|
|
8188
|
-
return (field) => !!field.file;
|
|
8189
|
-
},
|
|
8190
|
-
error: { message: "should be a file" }
|
|
8191
|
-
});
|
|
8192
|
-
}
|
|
8193
|
-
/**
|
|
8194
|
-
* These export configurations enable JS and TS developers
|
|
8195
|
-
* to consumer fastify in whatever way best suits their needs.
|
|
8196
|
-
*/
|
|
8197
|
-
module.exports = fp(fastifyMultipart, {
|
|
8198
|
-
fastify: "5.x",
|
|
8199
|
-
name: "@fastify/multipart"
|
|
8200
|
-
});
|
|
8201
|
-
module.exports.default = fastifyMultipart;
|
|
8202
|
-
module.exports.fastifyMultipart = fastifyMultipart;
|
|
8203
|
-
module.exports.ajvFilePlugin = ajvFilePlugin;
|
|
8204
|
-
})))(), 1);
|
|
5808
|
+
//#region ../server/dist/app-Frne_Mbn.mjs
|
|
8205
5809
|
var __defProp = Object.defineProperty;
|
|
8206
5810
|
var __exportAll = (all, no_symbols) => {
|
|
8207
5811
|
let target = {};
|
|
@@ -8996,7 +6600,7 @@ async function deleteAdapterConfig(db, id) {
|
|
|
8996
6600
|
const [row] = await db.delete(adapterConfigs).where(eq(adapterConfigs.id, id)).returning();
|
|
8997
6601
|
if (!row) throw new NotFoundError(`Adapter config "${id}" not found`);
|
|
8998
6602
|
}
|
|
8999
|
-
const log$4 = createLogger("AdminAdapters");
|
|
6603
|
+
const log$4 = createLogger$1("AdminAdapters");
|
|
9000
6604
|
function parseId(raw) {
|
|
9001
6605
|
const id = Number(raw);
|
|
9002
6606
|
if (!Number.isInteger(id) || id <= 0) throw new BadRequestError(`Invalid adapter ID: "${raw}"`);
|
|
@@ -9101,8 +6705,7 @@ async function adminAgentClientStatusRoutes(app) {
|
|
|
9101
6705
|
}
|
|
9102
6706
|
async function adminAgentConfigRoutes(app) {
|
|
9103
6707
|
app.get("/:uuid/config", async (request) => {
|
|
9104
|
-
|
|
9105
|
-
await assertAgentVisible(app.db, scope, request.params.uuid);
|
|
6708
|
+
await assertCanManage(app.db, memberScope(request), request.params.uuid);
|
|
9106
6709
|
return await app.configService.get(request.params.uuid);
|
|
9107
6710
|
});
|
|
9108
6711
|
app.patch("/:uuid/config", async (request) => {
|
|
@@ -12313,99 +9916,6 @@ async function adminTaskRoutes(app) {
|
|
|
12313
9916
|
return getTaskHealth(app.db, request.params.taskId);
|
|
12314
9917
|
});
|
|
12315
9918
|
}
|
|
12316
|
-
const UPLOADS_DIR = join(DEFAULT_DATA_DIR$1, "uploads");
|
|
12317
|
-
const MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
12318
|
-
const ALLOWED_MIME_TYPES = new Set([
|
|
12319
|
-
"image/png",
|
|
12320
|
-
"image/jpeg",
|
|
12321
|
-
"image/gif",
|
|
12322
|
-
"image/webp",
|
|
12323
|
-
"image/svg+xml"
|
|
12324
|
-
]);
|
|
12325
|
-
function ensureUploadsDir() {
|
|
12326
|
-
if (!existsSync(UPLOADS_DIR)) mkdirSync(UPLOADS_DIR, { recursive: true });
|
|
12327
|
-
}
|
|
12328
|
-
async function adminUploadRoutes(app) {
|
|
12329
|
-
ensureUploadsDir();
|
|
12330
|
-
/** POST /admin/uploads — upload a file, returns URL */
|
|
12331
|
-
app.post("/", async (request, reply) => {
|
|
12332
|
-
requireMember(request);
|
|
12333
|
-
const data = await request.file();
|
|
12334
|
-
if (!data) return reply.status(400).send({ error: "No file provided" });
|
|
12335
|
-
const mimeType = data.mimetype;
|
|
12336
|
-
if (!ALLOWED_MIME_TYPES.has(mimeType)) return reply.status(400).send({ error: `Unsupported file type: ${mimeType}. Allowed: ${[...ALLOWED_MIME_TYPES].join(", ")}` });
|
|
12337
|
-
const ext = extname(data.filename) || mimeExtension(mimeType);
|
|
12338
|
-
const uniqueName = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "").slice(0, 14)}_${randomUUID().slice(0, 8)}${ext}`;
|
|
12339
|
-
const filePath = join(UPLOADS_DIR, uniqueName);
|
|
12340
|
-
let totalSize = 0;
|
|
12341
|
-
const writeStream = createWriteStream(filePath);
|
|
12342
|
-
try {
|
|
12343
|
-
const fileStream = data.file;
|
|
12344
|
-
for await (const chunk of fileStream) {
|
|
12345
|
-
totalSize += chunk.length;
|
|
12346
|
-
if (totalSize > MAX_FILE_SIZE) {
|
|
12347
|
-
writeStream.destroy();
|
|
12348
|
-
try {
|
|
12349
|
-
unlinkSync(filePath);
|
|
12350
|
-
} catch {}
|
|
12351
|
-
return reply.status(400).send({ error: `File too large. Maximum size: ${MAX_FILE_SIZE / 1024 / 1024}MB` });
|
|
12352
|
-
}
|
|
12353
|
-
writeStream.write(chunk);
|
|
12354
|
-
}
|
|
12355
|
-
writeStream.end();
|
|
12356
|
-
await new Promise((resolve, reject) => {
|
|
12357
|
-
writeStream.on("finish", resolve);
|
|
12358
|
-
writeStream.on("error", reject);
|
|
12359
|
-
});
|
|
12360
|
-
} catch (err) {
|
|
12361
|
-
writeStream.destroy();
|
|
12362
|
-
throw err;
|
|
12363
|
-
}
|
|
12364
|
-
const url = `/api/v1/uploads/${uniqueName}`;
|
|
12365
|
-
return reply.status(201).send({
|
|
12366
|
-
url,
|
|
12367
|
-
filename: data.filename,
|
|
12368
|
-
storedName: uniqueName,
|
|
12369
|
-
mimeType,
|
|
12370
|
-
size: totalSize
|
|
12371
|
-
});
|
|
12372
|
-
});
|
|
12373
|
-
}
|
|
12374
|
-
/** Public routes — GET uploaded files (URL contains random UUID, not guessable) */
|
|
12375
|
-
async function publicUploadRoutes(app) {
|
|
12376
|
-
ensureUploadsDir();
|
|
12377
|
-
/** GET /uploads/:filename — serve uploaded file without auth */
|
|
12378
|
-
app.get("/:filename", async (request, reply) => {
|
|
12379
|
-
const { filename } = request.params;
|
|
12380
|
-
if (filename.includes("/") || filename.includes("..")) return reply.status(400).send({ error: "Invalid filename" });
|
|
12381
|
-
const filePath = join(UPLOADS_DIR, filename);
|
|
12382
|
-
if (!existsSync(filePath)) return reply.status(404).send({ error: "File not found" });
|
|
12383
|
-
const contentType = extensionToMime(extname(filename).toLowerCase()) ?? "application/octet-stream";
|
|
12384
|
-
const stream = createReadStream(filePath);
|
|
12385
|
-
return reply.type(contentType).send(stream);
|
|
12386
|
-
});
|
|
12387
|
-
}
|
|
12388
|
-
function mimeExtension(mime) {
|
|
12389
|
-
switch (mime) {
|
|
12390
|
-
case "image/png": return ".png";
|
|
12391
|
-
case "image/jpeg": return ".jpg";
|
|
12392
|
-
case "image/gif": return ".gif";
|
|
12393
|
-
case "image/webp": return ".webp";
|
|
12394
|
-
case "image/svg+xml": return ".svg";
|
|
12395
|
-
default: return "";
|
|
12396
|
-
}
|
|
12397
|
-
}
|
|
12398
|
-
function extensionToMime(ext) {
|
|
12399
|
-
switch (ext) {
|
|
12400
|
-
case ".png": return "image/png";
|
|
12401
|
-
case ".jpg":
|
|
12402
|
-
case ".jpeg": return "image/jpeg";
|
|
12403
|
-
case ".gif": return "image/gif";
|
|
12404
|
-
case ".webp": return "image/webp";
|
|
12405
|
-
case ".svg": return "image/svg+xml";
|
|
12406
|
-
default: return null;
|
|
12407
|
-
}
|
|
12408
|
-
}
|
|
12409
9919
|
async function loadVisibleAgentIds(db, organizationId, memberId) {
|
|
12410
9920
|
const rows = await db.select({ id: agents.uuid }).from(agents).where(and(eq(agents.organizationId, organizationId), ne(agents.status, AGENT_STATUSES.DELETED), or(eq(agents.visibility, AGENT_VISIBILITY.ORGANIZATION), eq(agents.managerId, memberId))));
|
|
12411
9921
|
return new Set(rows.map((r) => r.id));
|
|
@@ -12574,7 +10084,7 @@ async function agentConfigRoutes(app) {
|
|
|
12574
10084
|
return await app.configService.getDecrypted(identity.uuid);
|
|
12575
10085
|
});
|
|
12576
10086
|
}
|
|
12577
|
-
const log$3 = createLogger("AgentFeishuBot");
|
|
10087
|
+
const log$3 = createLogger$1("AgentFeishuBot");
|
|
12578
10088
|
async function agentFeishuBotRoutes(app) {
|
|
12579
10089
|
/**
|
|
12580
10090
|
* PUT /agent/me/feishu-bot
|
|
@@ -12839,7 +10349,7 @@ async function agentMeRoutes(app) {
|
|
|
12839
10349
|
};
|
|
12840
10350
|
});
|
|
12841
10351
|
}
|
|
12842
|
-
const log$2 = createLogger("AgentMessages");
|
|
10352
|
+
const log$2 = createLogger$1("AgentMessages");
|
|
12843
10353
|
const editMessageSchema = z.object({
|
|
12844
10354
|
format: z.string().optional(),
|
|
12845
10355
|
content: z.unknown()
|
|
@@ -13819,7 +11329,7 @@ async function memberRoutes(app) {
|
|
|
13819
11329
|
return reply.status(204).send();
|
|
13820
11330
|
});
|
|
13821
11331
|
}
|
|
13822
|
-
const log$1 = createLogger("GithubWebhook");
|
|
11332
|
+
const log$1 = createLogger$1("GithubWebhook");
|
|
13823
11333
|
const GITHUB_ADAPTER_ID = "github-adapter";
|
|
13824
11334
|
function verifySignature(secret, rawBody, signatureHeader) {
|
|
13825
11335
|
const expected = `sha256=${createHmac("sha256", secret).update(rawBody).digest("hex")}`;
|
|
@@ -14886,7 +12396,7 @@ function formatForFeishu(format, content) {
|
|
|
14886
12396
|
content: JSON.stringify({ text })
|
|
14887
12397
|
};
|
|
14888
12398
|
}
|
|
14889
|
-
const log = createLogger("BackgroundTasks");
|
|
12399
|
+
const log = createLogger$1("BackgroundTasks");
|
|
14890
12400
|
function createBackgroundTasks(app, instanceId, adapterManager, kaelRuntime) {
|
|
14891
12401
|
let inboxTimer = null;
|
|
14892
12402
|
let heartbeatTimer = null;
|
|
@@ -15529,7 +13039,6 @@ async function buildApp(config) {
|
|
|
15529
13039
|
const listenClient = postgres(config.database.url, { max: 1 });
|
|
15530
13040
|
const notifier = createNotifier(listenClient);
|
|
15531
13041
|
await app.register(websocket);
|
|
15532
|
-
await app.register(import_multipart.default, { limits: { fileSize: 10 * 1024 * 1024 } });
|
|
15533
13042
|
const corsOrigin = config.cors?.origin;
|
|
15534
13043
|
const isDev = process.env.NODE_ENV !== "production";
|
|
15535
13044
|
await app.register(cors, {
|
|
@@ -15568,14 +13077,12 @@ async function buildApp(config) {
|
|
|
15568
13077
|
await api.register(authRoutes, { prefix: "/auth" });
|
|
15569
13078
|
await api.register(contextTreeInfoRoutes, { prefix: "/context-tree" });
|
|
15570
13079
|
await api.register(bootstrapConfigRoutes, { prefix: "/bootstrap" });
|
|
15571
|
-
await api.register(publicUploadRoutes, { prefix: "/uploads" });
|
|
15572
13080
|
await api.register(async (adminApp) => {
|
|
15573
13081
|
adminApp.addHook("onRequest", memberAuth);
|
|
15574
13082
|
await adminApp.register(adminAgentRoutes);
|
|
15575
13083
|
}, { prefix: "/admin/agents" });
|
|
15576
13084
|
await api.register(async (adminApp) => {
|
|
15577
13085
|
adminApp.addHook("onRequest", memberAuth);
|
|
15578
|
-
adminApp.addHook("onRequest", adminOnly);
|
|
15579
13086
|
await adminApp.register(adminAgentConfigRoutes);
|
|
15580
13087
|
}, { prefix: "/admin/agents" });
|
|
15581
13088
|
await api.register(async (adminApp) => {
|
|
@@ -15615,10 +13122,6 @@ async function buildApp(config) {
|
|
|
15615
13122
|
adminApp.addHook("onRequest", memberAuth);
|
|
15616
13123
|
await adminApp.register(adminChatRoutes);
|
|
15617
13124
|
}, { prefix: "/admin/chats" });
|
|
15618
|
-
await api.register(async (adminApp) => {
|
|
15619
|
-
adminApp.addHook("onRequest", memberAuth);
|
|
15620
|
-
await adminApp.register(adminUploadRoutes);
|
|
15621
|
-
}, { prefix: "/admin/uploads" });
|
|
15622
13125
|
await api.register(async (adminApp) => {
|
|
15623
13126
|
adminApp.addHook("onRequest", memberAuth);
|
|
15624
13127
|
await adminApp.register(adminClientRoutes);
|
|
@@ -15695,7 +13198,7 @@ async function buildApp(config) {
|
|
|
15695
13198
|
notifier,
|
|
15696
13199
|
broadcast: broadcastToAdmins
|
|
15697
13200
|
});
|
|
15698
|
-
const hotReloadLog = createLogger("HotReload");
|
|
13201
|
+
const hotReloadLog = createLogger$1("HotReload");
|
|
15699
13202
|
notifier.onConfigChange((configType) => {
|
|
15700
13203
|
if (configType === "adapter_configs") {
|
|
15701
13204
|
adapterManager.reload().catch((err) => hotReloadLog.error({ err }, "adapter hot-reload failed (PG NOTIFY)"));
|
|
@@ -15763,7 +13266,7 @@ function resolveCommandVersion(moduleUrl = import.meta.url) {
|
|
|
15763
13266
|
const code = err.code;
|
|
15764
13267
|
if (code !== "ENOENT" && code !== "ENOTDIR") {
|
|
15765
13268
|
const message = err instanceof Error ? err.message : String(err);
|
|
15766
|
-
|
|
13269
|
+
print.line(`[first-tree-hub] warning: could not read ${dir}/package.json: ${message}\n`);
|
|
15767
13270
|
}
|
|
15768
13271
|
}
|
|
15769
13272
|
const parent = dirname(dir);
|
|
@@ -15786,7 +13289,7 @@ const COMMAND_VERSION = resolveCommandVersion();
|
|
|
15786
13289
|
* 7. Start Fastify server
|
|
15787
13290
|
*/
|
|
15788
13291
|
async function startServer(options) {
|
|
15789
|
-
|
|
13292
|
+
print.line(`\n First Tree Hub v${COMMAND_VERSION}\n\n`);
|
|
15790
13293
|
const cliArgs = {};
|
|
15791
13294
|
if (options.port !== void 0) cliArgs.server = { port: options.port };
|
|
15792
13295
|
if (options.host !== void 0) cliArgs.server = {
|
|
@@ -15828,11 +13331,11 @@ async function startServer(options) {
|
|
|
15828
13331
|
instanceId: `srv_${randomUUID().slice(0, 8)}`,
|
|
15829
13332
|
commandVersion: COMMAND_VERSION
|
|
15830
13333
|
};
|
|
15831
|
-
const { initTelemetry, shutdownTelemetry } = await import("./observability-
|
|
13334
|
+
const { initTelemetry, shutdownTelemetry } = await import("./observability-hDEdrmMS.mjs");
|
|
15832
13335
|
await initTelemetry(serverConfig.observability.tracing, config.instanceId);
|
|
15833
13336
|
const app = await buildApp(config);
|
|
15834
13337
|
const shutdown = async () => {
|
|
15835
|
-
|
|
13338
|
+
print.line("\n Shutting down...\n");
|
|
15836
13339
|
try {
|
|
15837
13340
|
await app.close();
|
|
15838
13341
|
} finally {
|
|
@@ -15849,8 +13352,8 @@ async function startServer(options) {
|
|
|
15849
13352
|
blank();
|
|
15850
13353
|
status("Server", `running at http://${config.server.host}:${config.server.port}`);
|
|
15851
13354
|
blank();
|
|
15852
|
-
|
|
15853
|
-
|
|
13355
|
+
print.line(" Open the URL above in your browser to get started.\n");
|
|
13356
|
+
print.line(" Press Ctrl+C to stop.\n\n");
|
|
15854
13357
|
}
|
|
15855
13358
|
/**
|
|
15856
13359
|
* Resolve web dist path.
|
|
@@ -15878,6 +13381,175 @@ function resolveWebDist() {
|
|
|
15878
13381
|
} catch {}
|
|
15879
13382
|
}
|
|
15880
13383
|
//#endregion
|
|
13384
|
+
//#region src/core/service-logs.ts
|
|
13385
|
+
const LOG_DIR = join(DEFAULT_HOME_DIR$1, "logs");
|
|
13386
|
+
const PRIMARY_LOG = join(LOG_DIR, "client.log");
|
|
13387
|
+
const FALLBACK_STDOUT = join(LOG_DIR, "client.stdout.log");
|
|
13388
|
+
const FALLBACK_STDERR = join(LOG_DIR, "client.stderr.log");
|
|
13389
|
+
/**
|
|
13390
|
+
* Duration string → milliseconds. Accepts `10s`, `5m`, `2h`, `1d`; rejects
|
|
13391
|
+
* everything else. Keeps the parser tiny rather than pulling in a library —
|
|
13392
|
+
* the `--since` flag is the only consumer.
|
|
13393
|
+
*/
|
|
13394
|
+
function parseDuration(input) {
|
|
13395
|
+
const match = /^(\d+)\s*(s|m|h|d)$/.exec(input.trim());
|
|
13396
|
+
if (!match) throw new Error(`invalid duration "${input}" (expected e.g. 30s, 5m, 2h, 1d)`);
|
|
13397
|
+
return Number(match[1]) * ({
|
|
13398
|
+
s: 1e3,
|
|
13399
|
+
m: 6e4,
|
|
13400
|
+
h: 36e5,
|
|
13401
|
+
d: 864e5
|
|
13402
|
+
}[match[2]] ?? 0);
|
|
13403
|
+
}
|
|
13404
|
+
const LEVEL_RANK = {
|
|
13405
|
+
trace: 10,
|
|
13406
|
+
debug: 20,
|
|
13407
|
+
info: 30,
|
|
13408
|
+
warn: 40,
|
|
13409
|
+
error: 50,
|
|
13410
|
+
fatal: 60
|
|
13411
|
+
};
|
|
13412
|
+
/** Rotated log files, newest-first. Missing files are silently skipped. */
|
|
13413
|
+
function listLogFilesNewestFirst() {
|
|
13414
|
+
const files = [];
|
|
13415
|
+
if (existsSync(PRIMARY_LOG)) files.push(PRIMARY_LOG);
|
|
13416
|
+
for (let i = 1;; i++) {
|
|
13417
|
+
const p = `${PRIMARY_LOG}.${i}`;
|
|
13418
|
+
if (!existsSync(p)) break;
|
|
13419
|
+
files.push(p);
|
|
13420
|
+
}
|
|
13421
|
+
return files;
|
|
13422
|
+
}
|
|
13423
|
+
/** Supervisor fallback files (raw stdout/stderr, not NDJSON). Missing files skipped. */
|
|
13424
|
+
function listFallbackFiles() {
|
|
13425
|
+
const files = [];
|
|
13426
|
+
if (existsSync(FALLBACK_STDERR)) files.push(FALLBACK_STDERR);
|
|
13427
|
+
if (existsSync(FALLBACK_STDOUT)) files.push(FALLBACK_STDOUT);
|
|
13428
|
+
return files;
|
|
13429
|
+
}
|
|
13430
|
+
function matchesFilters(obj, minLevel, cutoffMs) {
|
|
13431
|
+
if (minLevel !== void 0) {
|
|
13432
|
+
const lvl = typeof obj.level === "number" ? obj.level : NaN;
|
|
13433
|
+
if (!Number.isFinite(lvl) || lvl < minLevel) return false;
|
|
13434
|
+
}
|
|
13435
|
+
if (cutoffMs !== void 0) {
|
|
13436
|
+
const t = parseLogTime(obj.time);
|
|
13437
|
+
if (t === null || t < cutoffMs) return false;
|
|
13438
|
+
}
|
|
13439
|
+
return true;
|
|
13440
|
+
}
|
|
13441
|
+
/** Logger writes `time` as a local-ish string (`YYYY-MM-DD HH:mm:ss`). */
|
|
13442
|
+
function parseLogTime(value) {
|
|
13443
|
+
if (typeof value === "number") return value;
|
|
13444
|
+
if (typeof value !== "string") return null;
|
|
13445
|
+
const iso = value.replace(" ", "T");
|
|
13446
|
+
const ms = Date.parse(iso);
|
|
13447
|
+
return Number.isFinite(ms) ? ms : null;
|
|
13448
|
+
}
|
|
13449
|
+
function renderLine(line, json) {
|
|
13450
|
+
if (!line.trim()) return null;
|
|
13451
|
+
if (json) return `${line}\n`;
|
|
13452
|
+
try {
|
|
13453
|
+
return formatPrettyEntry$1(line);
|
|
13454
|
+
} catch {
|
|
13455
|
+
return `${line}\n`;
|
|
13456
|
+
}
|
|
13457
|
+
}
|
|
13458
|
+
function processLogLine(line, minLevel, cutoffMs, json) {
|
|
13459
|
+
let obj;
|
|
13460
|
+
try {
|
|
13461
|
+
obj = JSON.parse(line);
|
|
13462
|
+
} catch {
|
|
13463
|
+
return json ? null : `${line}\n`;
|
|
13464
|
+
}
|
|
13465
|
+
if (!matchesFilters(obj, minLevel, cutoffMs)) return null;
|
|
13466
|
+
return renderLine(line, json);
|
|
13467
|
+
}
|
|
13468
|
+
async function readFileLines(path, minLevel, cutoffMs, json) {
|
|
13469
|
+
const rl = createInterface({ input: createReadStream(path, { encoding: "utf8" }) });
|
|
13470
|
+
for await (const line of rl) {
|
|
13471
|
+
const rendered = processLogLine(line, minLevel, cutoffMs, json);
|
|
13472
|
+
if (rendered) process.stdout.write(rendered);
|
|
13473
|
+
}
|
|
13474
|
+
}
|
|
13475
|
+
/**
|
|
13476
|
+
* Read a supervisor fallback file (launchd / systemd stdout/stderr capture).
|
|
13477
|
+
* These are plain text, not NDJSON: level and time filters don't apply, so we
|
|
13478
|
+
* honour `--since` by dropping the whole file when its mtime predates the
|
|
13479
|
+
* cutoff and otherwise pass every line through. In pretty mode each line is
|
|
13480
|
+
* tagged with the source so operators can tell it apart from pino output; in
|
|
13481
|
+
* `--json` mode we emit a synthetic record so NDJSON consumers keep one
|
|
13482
|
+
* object per line.
|
|
13483
|
+
*/
|
|
13484
|
+
async function readFallbackFile(path, cutoffMs, json) {
|
|
13485
|
+
try {
|
|
13486
|
+
const mtime = statSync(path).mtimeMs;
|
|
13487
|
+
if (cutoffMs !== void 0 && mtime < cutoffMs) return;
|
|
13488
|
+
} catch {
|
|
13489
|
+
return;
|
|
13490
|
+
}
|
|
13491
|
+
const source = path.endsWith(".stderr.log") ? "supervisor:stderr" : "supervisor:stdout";
|
|
13492
|
+
const rl = createInterface({ input: createReadStream(path, { encoding: "utf8" }) });
|
|
13493
|
+
for await (const line of rl) {
|
|
13494
|
+
if (!line.trim()) continue;
|
|
13495
|
+
if (json) process.stdout.write(`${JSON.stringify({
|
|
13496
|
+
source,
|
|
13497
|
+
line
|
|
13498
|
+
})}\n`);
|
|
13499
|
+
else process.stdout.write(`[${source}] ${line}\n`);
|
|
13500
|
+
}
|
|
13501
|
+
}
|
|
13502
|
+
/**
|
|
13503
|
+
* Print existing log history, applying filters. `--tail` then switches to
|
|
13504
|
+
* follow mode and keeps printing new lines as the active file grows; rotation
|
|
13505
|
+
* is not handled during the tail (a follow-up rotation will simply stop
|
|
13506
|
+
* emitting new lines — operator can re-run the command).
|
|
13507
|
+
*/
|
|
13508
|
+
async function showServiceLogs(options) {
|
|
13509
|
+
if (!existsSync(LOG_DIR)) {
|
|
13510
|
+
print.status("logs", `directory not found: ${LOG_DIR}`);
|
|
13511
|
+
return;
|
|
13512
|
+
}
|
|
13513
|
+
const minLevel = options.level ? LEVEL_RANK[options.level] : void 0;
|
|
13514
|
+
const cutoffMs = options.sinceMs !== void 0 ? Date.now() - options.sinceMs : void 0;
|
|
13515
|
+
for (const f of listFallbackFiles()) await readFallbackFile(f, cutoffMs, options.json);
|
|
13516
|
+
const files = listLogFilesNewestFirst().reverse();
|
|
13517
|
+
for (const f of files) await readFileLines(f, minLevel, cutoffMs, options.json);
|
|
13518
|
+
if (!options.tail) return;
|
|
13519
|
+
if (!existsSync(PRIMARY_LOG)) print.status("tail", "waiting for client.log to appear...");
|
|
13520
|
+
await new Promise((resolve) => {
|
|
13521
|
+
let position = existsSync(PRIMARY_LOG) ? statSync(PRIMARY_LOG).size : 0;
|
|
13522
|
+
const onChange = () => {
|
|
13523
|
+
if (!existsSync(PRIMARY_LOG)) return;
|
|
13524
|
+
const current = statSync(PRIMARY_LOG).size;
|
|
13525
|
+
if (current < position) position = 0;
|
|
13526
|
+
if (current <= position) return;
|
|
13527
|
+
const stream = createReadStream(PRIMARY_LOG, {
|
|
13528
|
+
start: position,
|
|
13529
|
+
end: current - 1,
|
|
13530
|
+
encoding: "utf8"
|
|
13531
|
+
});
|
|
13532
|
+
position = current;
|
|
13533
|
+
createInterface({ input: stream }).on("line", (line) => {
|
|
13534
|
+
const rendered = processLogLine(line, minLevel, cutoffMs, options.json);
|
|
13535
|
+
if (rendered) process.stdout.write(rendered);
|
|
13536
|
+
});
|
|
13537
|
+
};
|
|
13538
|
+
watchFile(PRIMARY_LOG, { interval: 500 }, onChange);
|
|
13539
|
+
process.once("SIGINT", () => {
|
|
13540
|
+
unwatchFile(PRIMARY_LOG, onChange);
|
|
13541
|
+
resolve();
|
|
13542
|
+
});
|
|
13543
|
+
});
|
|
13544
|
+
}
|
|
13545
|
+
/** Validated flag parsers the CLI layer can reuse without re-doing the work. */
|
|
13546
|
+
function validateLevel(value) {
|
|
13547
|
+
if (value === void 0) return void 0;
|
|
13548
|
+
const parsed = parseLogLevel$1(value);
|
|
13549
|
+
if (parsed.fellBack) throw new Error(`invalid --level "${value}" (expected one of ${LOG_LEVELS$1.join(", ")})`);
|
|
13550
|
+
return parsed.level;
|
|
13551
|
+
}
|
|
13552
|
+
//#endregion
|
|
15881
13553
|
//#region src/core/update.ts
|
|
15882
13554
|
const PACKAGE_NAME = "@agent-team-foundation/first-tree-hub";
|
|
15883
13555
|
/**
|
|
@@ -15947,7 +13619,7 @@ async function installGlobalLatest() {
|
|
|
15947
13619
|
child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
15948
13620
|
child.stderr.on("data", (chunk) => {
|
|
15949
13621
|
stderrChunks.push(chunk);
|
|
15950
|
-
|
|
13622
|
+
print.line(chunk.toString("utf8"));
|
|
15951
13623
|
});
|
|
15952
13624
|
child.on("error", (err) => {
|
|
15953
13625
|
resolvePromise({
|
|
@@ -16031,27 +13703,27 @@ function createExecuteUpdate({ managed }) {
|
|
|
16031
13703
|
return async () => {
|
|
16032
13704
|
const mode = detectInstallMode();
|
|
16033
13705
|
if (mode === "source") {
|
|
16034
|
-
|
|
13706
|
+
print.line(" [update] Running from source checkout — self-update skipped. Use `git pull` instead.\n");
|
|
16035
13707
|
return { installed: false };
|
|
16036
13708
|
}
|
|
16037
13709
|
if (mode === "npx") {
|
|
16038
|
-
|
|
13710
|
+
print.line(" [update] Cannot self-update — not launched from a global npm install.\n Run `npm i -g @agent-team-foundation/first-tree-hub` manually.\n");
|
|
16039
13711
|
return { installed: false };
|
|
16040
13712
|
}
|
|
16041
|
-
|
|
13713
|
+
print.line(" [update] Running `npm install -g @agent-team-foundation/first-tree-hub@latest`...\n");
|
|
16042
13714
|
const result = await installGlobalLatest();
|
|
16043
13715
|
if (!result.ok) {
|
|
16044
|
-
|
|
13716
|
+
print.line(` [update] Install failed: ${result.reason}\n`);
|
|
16045
13717
|
return { installed: false };
|
|
16046
13718
|
}
|
|
16047
13719
|
const installed = result.installedVersion ?? "latest";
|
|
16048
13720
|
if (managed) {
|
|
16049
|
-
|
|
13721
|
+
print.line(` [update] Installed ${installed}. Restarting (exit 75).\n`);
|
|
16050
13722
|
process.exit(75);
|
|
16051
13723
|
}
|
|
16052
|
-
|
|
13724
|
+
print.line(` [update] Installed ${installed}. Restart the client manually (Ctrl+C then \`first-tree-hub client start\`) to pick up the new version.\n`);
|
|
16053
13725
|
return { installed: true };
|
|
16054
13726
|
};
|
|
16055
13727
|
}
|
|
16056
13728
|
//#endregion
|
|
16057
|
-
export {
|
|
13729
|
+
export { checkServerHealth as A, blank as B, runMigrations as C, checkDocker as D, checkDatabase as E, isDockerAvailable as F, SdkError as G, setJsonMode as H, stopPostgres as I, applyClientLoggerConfig as J, SessionRegistry as K, ClientRuntime as L, checkWebSocket as M, printResults as N, checkNodeVersion as O, ensurePostgres as P, createOwner as R, uninstallClientService as S, checkClientConfig as T, status as U, print as V, FirstTreeHubSDK as W, configureClientLoggerForService as Y, runHomeMigration as _, showServiceLogs as a, isServiceSupported as b, COMMAND_VERSION as c, promptMissingFields as d, formatCheckReport as f, saveOnboardState as g, onboardCreate as h, parseDuration as i, checkServerReachable as j, checkServerConfig as k, isInteractive as l, onboardCheck as m, declineUpdate as n, validateLevel as o, loadOnboardState as p, cleanWorkspaces as q, promptUpdate as r, startServer as s, createExecuteUpdate as t, promptAddAgent as u, getClientServiceStatus as v, checkAgentConfigs as w, resolveCliInvocation as x, installClientService as y, hasUser as z };
|