@lark-apaas/devtool-kits 1.2.12 → 1.2.14-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1394,8 +1394,8 @@ function checkForErrors(logs) {
1394
1394
  return false;
1395
1395
  }
1396
1396
  __name(checkForErrors, "checkForErrors");
1397
- function injectTemplateData(template, clientBasePath) {
1398
- return template.replace("{{.clientBasePath}}", clientBasePath);
1397
+ function injectTemplateData(template, clientBasePath, parentOrigin) {
1398
+ return template.replace("{{.clientBasePath}}", clientBasePath).replace("{{.parentOrigin}}", parentOrigin);
1399
1399
  }
1400
1400
  __name(injectTemplateData, "injectTemplateData");
1401
1401
  function handleDevProxyError(err, req, res, options) {
@@ -1433,7 +1433,8 @@ function handleDevProxyError(err, req, res, options) {
1433
1433
  console.log("[Proxy Error]: Compile error or non-connection error, showing error page");
1434
1434
  }
1435
1435
  const template = getErrorHtmlTemplate();
1436
- const html = injectTemplateData(template, clientBasePathWithoutSlash);
1436
+ const parentOrigin = process.env.FORCE_FRAMEWORK_DOMAIN_MAIN || "";
1437
+ const html = injectTemplateData(template, clientBasePathWithoutSlash, parentOrigin);
1437
1438
  res.writeHead(200, {
1438
1439
  "Content-Type": "text/html; charset=utf-8",
1439
1440
  "Cache-Control": "no-cache, no-store, must-revalidate",
@@ -1908,10 +1909,194 @@ function serializeError(error) {
1908
1909
  __name(serializeError, "serializeError");
1909
1910
 
1910
1911
  // src/middlewares/dev-logs/controller.ts
1911
- import { join as join3 } from "path";
1912
+ import { join as join4 } from "path";
1913
+
1914
+ // src/middlewares/dev-logs/services/file-reader.ts
1915
+ import { promises as fs8 } from "fs";
1916
+ async function readFileReverse(filePath, chunkSize, processLine) {
1917
+ const handle = await fs8.open(filePath, "r");
1918
+ try {
1919
+ const stats = await handle.stat();
1920
+ let position = stats.size;
1921
+ let remainder = "";
1922
+ while (position > 0) {
1923
+ const length = Math.min(chunkSize, position);
1924
+ position -= length;
1925
+ const buffer = Buffer.alloc(length);
1926
+ await handle.read(buffer, 0, length, position);
1927
+ let chunk = buffer.toString("utf8");
1928
+ if (remainder) {
1929
+ chunk += remainder;
1930
+ remainder = "";
1931
+ }
1932
+ const lines = chunk.split("\n");
1933
+ remainder = lines.shift() ?? "";
1934
+ for (let i = lines.length - 1; i >= 0; i -= 1) {
1935
+ if (lines[i]) {
1936
+ processLine(lines[i]);
1937
+ }
1938
+ }
1939
+ }
1940
+ if (remainder) {
1941
+ processLine(remainder);
1942
+ }
1943
+ } finally {
1944
+ await handle.close();
1945
+ }
1946
+ }
1947
+ __name(readFileReverse, "readFileReverse");
1948
+ function buildPaginatedResponse(items, page, pageSize) {
1949
+ const totalItems = items.length;
1950
+ const totalPages = totalItems === 0 ? 0 : Math.ceil(totalItems / pageSize);
1951
+ const startIndex = (page - 1) * pageSize;
1952
+ const endIndex = Math.min(startIndex + pageSize, totalItems);
1953
+ const pagedItems = items.slice(startIndex, endIndex).map((builder) => ({
1954
+ traceId: builder.traceId,
1955
+ method: builder.method,
1956
+ path: builder.path,
1957
+ startTime: builder.startTime,
1958
+ endTime: builder.endTime,
1959
+ statusCode: builder.statusCode,
1960
+ durationMs: builder.durationMs,
1961
+ entries: builder.entries.slice().reverse()
1962
+ }));
1963
+ return {
1964
+ page,
1965
+ pageSize,
1966
+ totalCalls: totalItems,
1967
+ totalPages,
1968
+ calls: pagedItems
1969
+ };
1970
+ }
1971
+ __name(buildPaginatedResponse, "buildPaginatedResponse");
1912
1972
 
1913
- // src/middlewares/dev-logs/services.ts
1914
- import { createReadStream, promises as fs8 } from "fs";
1973
+ // src/middlewares/dev-logs/services/parsers.ts
1974
+ function generateUUID() {
1975
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1976
+ const r = Math.random() * 16 | 0;
1977
+ const v = c === "x" ? r : r & 3 | 8;
1978
+ return v.toString(16);
1979
+ });
1980
+ }
1981
+ __name(generateUUID, "generateUUID");
1982
+ function mapPinoLevelToServerLogLevel(pinoLevel) {
1983
+ if (typeof pinoLevel === "string") {
1984
+ const lower = pinoLevel.toLowerCase();
1985
+ if (lower === "fatal") return "fatal";
1986
+ if (lower === "error") return "error";
1987
+ if (lower === "warn" || lower === "warning") return "warn";
1988
+ if (lower === "info" || lower === "log") return "log";
1989
+ if (lower === "debug") return "debug";
1990
+ if (lower === "trace" || lower === "verbose") return "verbose";
1991
+ return "log";
1992
+ }
1993
+ if (pinoLevel >= 60) return "fatal";
1994
+ if (pinoLevel >= 50) return "error";
1995
+ if (pinoLevel >= 40) return "warn";
1996
+ if (pinoLevel >= 30) return "log";
1997
+ if (pinoLevel >= 20) return "debug";
1998
+ return "verbose";
1999
+ }
2000
+ __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2001
+ function extractLogLevel(text) {
2002
+ const lower = text.toLowerCase();
2003
+ if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2004
+ if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2005
+ if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2006
+ if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2007
+ if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2008
+ return "log";
2009
+ }
2010
+ __name(extractLogLevel, "extractLogLevel");
2011
+ function parsePinoLog(line, source) {
2012
+ try {
2013
+ const pinoLog = JSON.parse(line);
2014
+ const id = generateUUID();
2015
+ return {
2016
+ id,
2017
+ level: mapPinoLevelToServerLogLevel(pinoLog.level),
2018
+ timestamp: new Date(pinoLog.time).getTime(),
2019
+ message: pinoLog.message || pinoLog.msg || "",
2020
+ context: pinoLog.context || null,
2021
+ traceId: pinoLog.trace_id || null,
2022
+ userId: pinoLog.user_id || null,
2023
+ appId: pinoLog.app_id || null,
2024
+ tenantId: pinoLog.tenant_id || null,
2025
+ stack: pinoLog.stack || null,
2026
+ meta: {
2027
+ pid: pinoLog.pid,
2028
+ hostname: pinoLog.hostname,
2029
+ path: pinoLog.path,
2030
+ method: pinoLog.method,
2031
+ statusCode: pinoLog.status_code,
2032
+ durationMs: pinoLog.duration_ms,
2033
+ ip: pinoLog.ip,
2034
+ requestBody: pinoLog.request_body,
2035
+ responseBody: pinoLog.response_body
2036
+ },
2037
+ tags: [
2038
+ source
2039
+ ]
2040
+ };
2041
+ } catch (error) {
2042
+ return null;
2043
+ }
2044
+ }
2045
+ __name(parsePinoLog, "parsePinoLog");
2046
+ function parseStdLog(line, source) {
2047
+ const id = generateUUID();
2048
+ const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2049
+ if (!match) {
2050
+ return {
2051
+ id,
2052
+ level: "log",
2053
+ timestamp: Date.now(),
2054
+ message: line,
2055
+ context: null,
2056
+ traceId: null,
2057
+ userId: null,
2058
+ appId: null,
2059
+ tenantId: null,
2060
+ stack: null,
2061
+ meta: null,
2062
+ tags: [
2063
+ source
2064
+ ]
2065
+ };
2066
+ }
2067
+ const [, timeStr, , content] = match;
2068
+ let timestamp;
2069
+ try {
2070
+ const isoStr = timeStr.replace(" ", "T");
2071
+ timestamp = new Date(isoStr).getTime();
2072
+ if (isNaN(timestamp)) {
2073
+ timestamp = Date.now();
2074
+ }
2075
+ } catch (error) {
2076
+ timestamp = Date.now();
2077
+ }
2078
+ const level = extractLogLevel(content);
2079
+ return {
2080
+ id,
2081
+ level,
2082
+ timestamp,
2083
+ message: content,
2084
+ context: null,
2085
+ traceId: null,
2086
+ userId: null,
2087
+ appId: null,
2088
+ tenantId: null,
2089
+ stack: null,
2090
+ meta: null,
2091
+ tags: [
2092
+ source
2093
+ ]
2094
+ };
2095
+ }
2096
+ __name(parseStdLog, "parseStdLog");
2097
+
2098
+ // src/middlewares/dev-logs/services/trace.service.ts
2099
+ import { createReadStream } from "fs";
1915
2100
  import { createInterface } from "readline";
1916
2101
  async function readLogEntriesByTrace(filePath, traceId, limit) {
1917
2102
  const exists = await fileExists(filePath);
@@ -2010,62 +2195,6 @@ async function readRecentTraceCalls(filePath, page, pageSize, pathFilter, method
2010
2195
  return buildPaginatedResponse(completedCalls, page, pageSize);
2011
2196
  }
2012
2197
  __name(readRecentTraceCalls, "readRecentTraceCalls");
2013
- async function readFileReverse(filePath, chunkSize, processLine) {
2014
- const handle = await fs8.open(filePath, "r");
2015
- try {
2016
- const stats = await handle.stat();
2017
- let position = stats.size;
2018
- let remainder = "";
2019
- while (position > 0) {
2020
- const length = Math.min(chunkSize, position);
2021
- position -= length;
2022
- const buffer = Buffer.alloc(length);
2023
- await handle.read(buffer, 0, length, position);
2024
- let chunk = buffer.toString("utf8");
2025
- if (remainder) {
2026
- chunk += remainder;
2027
- remainder = "";
2028
- }
2029
- const lines = chunk.split("\n");
2030
- remainder = lines.shift() ?? "";
2031
- for (let i = lines.length - 1; i >= 0; i -= 1) {
2032
- if (lines[i]) {
2033
- processLine(lines[i]);
2034
- }
2035
- }
2036
- }
2037
- if (remainder) {
2038
- processLine(remainder);
2039
- }
2040
- } finally {
2041
- await handle.close();
2042
- }
2043
- }
2044
- __name(readFileReverse, "readFileReverse");
2045
- function buildPaginatedResponse(items, page, pageSize) {
2046
- const totalItems = items.length;
2047
- const totalPages = totalItems === 0 ? 0 : Math.ceil(totalItems / pageSize);
2048
- const startIndex = (page - 1) * pageSize;
2049
- const endIndex = Math.min(startIndex + pageSize, totalItems);
2050
- const pagedItems = items.slice(startIndex, endIndex).map((builder) => ({
2051
- traceId: builder.traceId,
2052
- method: builder.method,
2053
- path: builder.path,
2054
- startTime: builder.startTime,
2055
- endTime: builder.endTime,
2056
- statusCode: builder.statusCode,
2057
- durationMs: builder.durationMs,
2058
- entries: builder.entries.slice().reverse()
2059
- }));
2060
- return {
2061
- page,
2062
- pageSize,
2063
- totalCalls: totalItems,
2064
- totalPages,
2065
- calls: pagedItems
2066
- };
2067
- }
2068
- __name(buildPaginatedResponse, "buildPaginatedResponse");
2069
2198
  async function readLogFilePage(filePath, page, pageSize) {
2070
2199
  if (!await fileExists(filePath)) {
2071
2200
  return void 0;
@@ -2121,6 +2250,11 @@ async function readLogFilePage(filePath, page, pageSize) {
2121
2250
  };
2122
2251
  }
2123
2252
  __name(readLogFilePage, "readLogFilePage");
2253
+
2254
+ // src/middlewares/dev-logs/services/server-log.service.ts
2255
+ import { createReadStream as createReadStream2 } from "fs";
2256
+ import { createInterface as createInterface2 } from "readline";
2257
+ import { join as join3 } from "path";
2124
2258
  async function readServerLogs(logDir, options = {}) {
2125
2259
  const limit = options.limit || 100;
2126
2260
  const offset = options.offset || 0;
@@ -2163,20 +2297,19 @@ async function readServerLogs(logDir, options = {}) {
2163
2297
  }
2164
2298
  __name(readServerLogs, "readServerLogs");
2165
2299
  async function readLogsBySource(logDir, source) {
2166
- const { join: join7 } = await import("path");
2167
2300
  let filePath;
2168
2301
  let parser;
2169
2302
  if (source === "server") {
2170
- filePath = join7(logDir, "server.log");
2303
+ filePath = join3(logDir, "server.log");
2171
2304
  parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "server"), "parser");
2172
2305
  } else if (source === "trace") {
2173
- filePath = join7(logDir, "trace.log");
2306
+ filePath = join3(logDir, "trace.log");
2174
2307
  parser = /* @__PURE__ */ __name((line) => parsePinoLog(line, "trace"), "parser");
2175
2308
  } else if (source === "server-std") {
2176
- filePath = join7(logDir, "server.std.log");
2309
+ filePath = join3(logDir, "server.std.log");
2177
2310
  parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "server-std"), "parser");
2178
2311
  } else if (source === "client-std") {
2179
- filePath = join7(logDir, "client.std.log");
2312
+ filePath = join3(logDir, "client.std.log");
2180
2313
  parser = /* @__PURE__ */ __name((line) => parseStdLog(line, "client-std"), "parser");
2181
2314
  } else {
2182
2315
  console.warn(`[readLogsBySource] Unknown source: ${source}`);
@@ -2190,10 +2323,10 @@ async function readLogsBySource(logDir, source) {
2190
2323
  let stream = null;
2191
2324
  let rl = null;
2192
2325
  try {
2193
- stream = createReadStream(filePath, {
2326
+ stream = createReadStream2(filePath, {
2194
2327
  encoding: "utf8"
2195
2328
  });
2196
- rl = createInterface({
2329
+ rl = createInterface2({
2197
2330
  input: stream,
2198
2331
  crlfDelay: Infinity
2199
2332
  });
@@ -2221,129 +2354,10 @@ async function readLogsBySource(logDir, source) {
2221
2354
  return logs;
2222
2355
  }
2223
2356
  __name(readLogsBySource, "readLogsBySource");
2224
- function parsePinoLog(line, source) {
2225
- try {
2226
- const pinoLog = JSON.parse(line);
2227
- const id = generateUUID();
2228
- return {
2229
- id,
2230
- level: mapPinoLevelToServerLogLevel(pinoLog.level),
2231
- timestamp: new Date(pinoLog.time).getTime(),
2232
- message: pinoLog.message || pinoLog.msg || "",
2233
- context: pinoLog.context || null,
2234
- traceId: pinoLog.trace_id || null,
2235
- userId: pinoLog.user_id || null,
2236
- appId: pinoLog.app_id || null,
2237
- tenantId: pinoLog.tenant_id || null,
2238
- stack: pinoLog.stack || null,
2239
- meta: {
2240
- pid: pinoLog.pid,
2241
- hostname: pinoLog.hostname,
2242
- path: pinoLog.path,
2243
- method: pinoLog.method,
2244
- statusCode: pinoLog.status_code,
2245
- durationMs: pinoLog.duration_ms,
2246
- ip: pinoLog.ip,
2247
- requestBody: pinoLog.request_body,
2248
- responseBody: pinoLog.response_body
2249
- },
2250
- tags: [
2251
- source
2252
- ]
2253
- };
2254
- } catch (error) {
2255
- return null;
2256
- }
2257
- }
2258
- __name(parsePinoLog, "parsePinoLog");
2259
- function parseStdLog(line, source) {
2260
- const id = generateUUID();
2261
- const match = line.match(/^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] \[(server|client)\] (.*)$/);
2262
- if (!match) {
2263
- return {
2264
- id,
2265
- level: "log",
2266
- timestamp: Date.now(),
2267
- message: line,
2268
- context: null,
2269
- traceId: null,
2270
- userId: null,
2271
- appId: null,
2272
- tenantId: null,
2273
- stack: null,
2274
- meta: null,
2275
- tags: [
2276
- source
2277
- ]
2278
- };
2279
- }
2280
- const [, timeStr, , content] = match;
2281
- let timestamp;
2282
- try {
2283
- const isoStr = timeStr.replace(" ", "T");
2284
- timestamp = new Date(isoStr).getTime();
2285
- if (isNaN(timestamp)) {
2286
- timestamp = Date.now();
2287
- }
2288
- } catch (error) {
2289
- timestamp = Date.now();
2290
- }
2291
- const level = extractLogLevel(content);
2292
- return {
2293
- id,
2294
- level,
2295
- timestamp,
2296
- message: content,
2297
- context: null,
2298
- traceId: null,
2299
- userId: null,
2300
- appId: null,
2301
- tenantId: null,
2302
- stack: null,
2303
- meta: null,
2304
- tags: [
2305
- source
2306
- ]
2307
- };
2308
- }
2309
- __name(parseStdLog, "parseStdLog");
2310
- function mapPinoLevelToServerLogLevel(pinoLevel) {
2311
- if (typeof pinoLevel === "string") {
2312
- const lower = pinoLevel.toLowerCase();
2313
- if (lower === "fatal") return "fatal";
2314
- if (lower === "error") return "error";
2315
- if (lower === "warn" || lower === "warning") return "warn";
2316
- if (lower === "info" || lower === "log") return "log";
2317
- if (lower === "debug") return "debug";
2318
- if (lower === "trace" || lower === "verbose") return "verbose";
2319
- return "log";
2320
- }
2321
- if (pinoLevel >= 60) return "fatal";
2322
- if (pinoLevel >= 50) return "error";
2323
- if (pinoLevel >= 40) return "warn";
2324
- if (pinoLevel >= 30) return "log";
2325
- if (pinoLevel >= 20) return "debug";
2326
- return "verbose";
2327
- }
2328
- __name(mapPinoLevelToServerLogLevel, "mapPinoLevelToServerLogLevel");
2329
- function extractLogLevel(text) {
2330
- const lower = text.toLowerCase();
2331
- if (lower.includes("fatal") || lower.includes("critical")) return "fatal";
2332
- if (lower.includes("error") || lower.includes("<e>") || lower.includes("\u2716")) return "error";
2333
- if (lower.includes("warn") || lower.includes("warning") || lower.includes("<w>") || lower.includes("\u26A0")) return "warn";
2334
- if (lower.includes("debug") || lower.includes("<d>")) return "debug";
2335
- if (lower.includes("verbose") || lower.includes("trace")) return "verbose";
2336
- return "log";
2337
- }
2338
- __name(extractLogLevel, "extractLogLevel");
2339
- function generateUUID() {
2340
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2341
- const r = Math.random() * 16 | 0;
2342
- const v = c === "x" ? r : r & 3 | 8;
2343
- return v.toString(16);
2344
- });
2345
- }
2346
- __name(generateUUID, "generateUUID");
2357
+
2358
+ // src/middlewares/dev-logs/services/trigger.service.ts
2359
+ import { createReadStream as createReadStream3 } from "fs";
2360
+ import { createInterface as createInterface3 } from "readline";
2347
2361
  async function readTriggerList(filePath, trigger, path8, limit, triggerID) {
2348
2362
  if (!await fileExists(filePath)) {
2349
2363
  return void 0;
@@ -2459,10 +2473,10 @@ async function readTriggerDetail(filePath, path8, instanceID) {
2459
2473
  return void 0;
2460
2474
  }
2461
2475
  const matches = [];
2462
- const stream = createReadStream(filePath, {
2476
+ const stream = createReadStream3(filePath, {
2463
2477
  encoding: "utf8"
2464
2478
  });
2465
- const rl = createInterface({
2479
+ const rl = createInterface3({
2466
2480
  input: stream,
2467
2481
  crlfDelay: Infinity
2468
2482
  });
@@ -2483,6 +2497,118 @@ async function readTriggerDetail(filePath, path8, instanceID) {
2483
2497
  }
2484
2498
  __name(readTriggerDetail, "readTriggerDetail");
2485
2499
 
2500
+ // src/middlewares/dev-logs/services/capability.service.ts
2501
+ async function readCapabilityTraceList(filePath, capabilityId, limit) {
2502
+ if (!await fileExists(filePath)) {
2503
+ return void 0;
2504
+ }
2505
+ const config = {
2506
+ chunkSize: 64 * 1024
2507
+ };
2508
+ const builders = /* @__PURE__ */ new Map();
2509
+ const completedTraces = [];
2510
+ const createCapabilityTraceBuilder = /* @__PURE__ */ __name((traceId, capId) => ({
2511
+ traceId,
2512
+ capabilityId: capId,
2513
+ hasCompleted: false,
2514
+ hasStartEntry: false
2515
+ }), "createCapabilityTraceBuilder");
2516
+ const shouldIncludeInCompletedTraces = /* @__PURE__ */ __name((builder) => {
2517
+ const alreadyAdded = completedTraces.some((trace) => trace.traceId === builder.traceId);
2518
+ if (alreadyAdded) {
2519
+ return false;
2520
+ }
2521
+ return builder.capabilityId === capabilityId;
2522
+ }, "shouldIncludeInCompletedTraces");
2523
+ const updateBuilderMetadata = /* @__PURE__ */ __name((builder, entry) => {
2524
+ if (entry.plugin_key && !builder.pluginKey) {
2525
+ builder.pluginKey = String(entry.plugin_key);
2526
+ }
2527
+ if (entry.action && !builder.action) {
2528
+ builder.action = String(entry.action);
2529
+ }
2530
+ const message = entry.message || "";
2531
+ if (message.includes("Executing capability") && !builder.hasStartEntry) {
2532
+ builder.hasStartEntry = true;
2533
+ builder.startTime = entry.time;
2534
+ if (entry.input) {
2535
+ builder.input = String(entry.input);
2536
+ }
2537
+ }
2538
+ if (message.includes("executed successfully")) {
2539
+ builder.hasCompleted = true;
2540
+ builder.endTime = entry.time;
2541
+ builder.status = "success";
2542
+ if (entry.output) {
2543
+ builder.output = String(entry.output);
2544
+ }
2545
+ if (entry.duration_ms) {
2546
+ builder.durationMs = Number(entry.duration_ms);
2547
+ }
2548
+ if (shouldIncludeInCompletedTraces(builder)) {
2549
+ completedTraces.push(builder);
2550
+ }
2551
+ }
2552
+ if (message.includes("execution failed")) {
2553
+ builder.hasCompleted = true;
2554
+ builder.endTime = entry.time;
2555
+ builder.status = "failed";
2556
+ if (entry.error) {
2557
+ builder.error = {
2558
+ message: String(entry.error)
2559
+ };
2560
+ }
2561
+ if (entry.duration_ms) {
2562
+ builder.durationMs = Number(entry.duration_ms);
2563
+ }
2564
+ if (shouldIncludeInCompletedTraces(builder)) {
2565
+ completedTraces.push(builder);
2566
+ }
2567
+ }
2568
+ }, "updateBuilderMetadata");
2569
+ const processLogEntry = /* @__PURE__ */ __name((entry) => {
2570
+ const { trace_id: traceId, capability_id: capId } = entry;
2571
+ if (!traceId || !capId || capId !== capabilityId) return;
2572
+ let builder = builders.get(traceId);
2573
+ if (!builder) {
2574
+ builder = createCapabilityTraceBuilder(traceId, capId);
2575
+ builders.set(traceId, builder);
2576
+ }
2577
+ updateBuilderMetadata(builder, entry);
2578
+ }, "processLogEntry");
2579
+ const processLine = /* @__PURE__ */ __name((line) => {
2580
+ const entry = parseLogLine2(line);
2581
+ if (entry?.capability_id) {
2582
+ processLogEntry(entry);
2583
+ }
2584
+ }, "processLine");
2585
+ await readFileReverse(filePath, config.chunkSize, processLine);
2586
+ completedTraces.sort((a, b) => {
2587
+ const timeA = a.endTime ? new Date(a.endTime).getTime() : 0;
2588
+ const timeB = b.endTime ? new Date(b.endTime).getTime() : 0;
2589
+ return timeB - timeA;
2590
+ });
2591
+ const limitedTraces = limit ? completedTraces.slice(0, limit) : completedTraces;
2592
+ return {
2593
+ capabilityId,
2594
+ totalTraces: limitedTraces.length,
2595
+ traces: limitedTraces.map((builder) => ({
2596
+ traceId: builder.traceId,
2597
+ capabilityId: builder.capabilityId,
2598
+ pluginKey: builder.pluginKey,
2599
+ action: builder.action,
2600
+ startTime: builder.startTime,
2601
+ endTime: builder.endTime,
2602
+ durationMs: builder.durationMs,
2603
+ status: builder.status || "failed",
2604
+ input: builder.input,
2605
+ output: builder.output,
2606
+ error: builder.error
2607
+ }))
2608
+ };
2609
+ }
2610
+ __name(readCapabilityTraceList, "readCapabilityTraceList");
2611
+
2486
2612
  // src/middlewares/dev-logs/controller.ts
2487
2613
  function handleNotFound(res, filePath, message = "Log file not found") {
2488
2614
  res.status(404).json({
@@ -2498,7 +2624,7 @@ function handleError(res, error, message = "Failed to read log file") {
2498
2624
  }
2499
2625
  __name(handleError, "handleError");
2500
2626
  function createGetTraceEntriesHandler(logDir) {
2501
- const appLogPath = join3(logDir, "server.log");
2627
+ const appLogPath = join4(logDir, "server.log");
2502
2628
  return async (req, res) => {
2503
2629
  const traceId = (req.params.traceId || "").trim();
2504
2630
  if (!traceId) {
@@ -2525,7 +2651,7 @@ function createGetTraceEntriesHandler(logDir) {
2525
2651
  }
2526
2652
  __name(createGetTraceEntriesHandler, "createGetTraceEntriesHandler");
2527
2653
  function createGetRecentTracesHandler(logDir) {
2528
- const traceLogPath = join3(logDir, "trace.log");
2654
+ const traceLogPath = join4(logDir, "trace.log");
2529
2655
  return async (req, res) => {
2530
2656
  const page = parsePositiveInt(req.query.page, 1);
2531
2657
  const pageSize = parseLimit(req.query.pageSize, 10, 100);
@@ -2602,7 +2728,7 @@ function createGetServerLogsHandler(logDir) {
2602
2728
  }
2603
2729
  __name(createGetServerLogsHandler, "createGetServerLogsHandler");
2604
2730
  function createGetTriggerListHandler(logDir) {
2605
- const traceLogPath = join3(logDir, "trace.log");
2731
+ const traceLogPath = join4(logDir, "trace.log");
2606
2732
  return async (req, res) => {
2607
2733
  const trigger = typeof req.query.trigger === "string" ? req.query.trigger.trim() : void 0;
2608
2734
  if (!trigger) {
@@ -2630,7 +2756,7 @@ function createGetTriggerListHandler(logDir) {
2630
2756
  }
2631
2757
  __name(createGetTriggerListHandler, "createGetTriggerListHandler");
2632
2758
  function createGetTriggerDetailHandler(logDir) {
2633
- const traceLogPath = join3(logDir, "server.log");
2759
+ const traceLogPath = join4(logDir, "server.log");
2634
2760
  return async (req, res) => {
2635
2761
  const instanceID = (req.params.instanceID || "").trim();
2636
2762
  if (!instanceID) {
@@ -2654,6 +2780,31 @@ function createGetTriggerDetailHandler(logDir) {
2654
2780
  };
2655
2781
  }
2656
2782
  __name(createGetTriggerDetailHandler, "createGetTriggerDetailHandler");
2783
+ function createGetCapabilityTraceListHandler(logDir) {
2784
+ const serverLogPath = join4(logDir, "server.log");
2785
+ return async (req, res) => {
2786
+ const capabilityId = typeof req.query.capability_id === "string" ? req.query.capability_id.trim() : void 0;
2787
+ if (!capabilityId) {
2788
+ return res.status(400).json({
2789
+ message: "capability_id is required"
2790
+ });
2791
+ }
2792
+ const limit = parseLimit(req.query.limit, 10, 200);
2793
+ try {
2794
+ const result = await readCapabilityTraceList(serverLogPath, capabilityId, limit);
2795
+ if (!result) {
2796
+ return handleNotFound(res, serverLogPath);
2797
+ }
2798
+ res.json({
2799
+ file: getRelativePath(serverLogPath),
2800
+ ...result
2801
+ });
2802
+ } catch (error) {
2803
+ handleError(res, error, "Failed to read server log");
2804
+ }
2805
+ };
2806
+ }
2807
+ __name(createGetCapabilityTraceListHandler, "createGetCapabilityTraceListHandler");
2657
2808
 
2658
2809
  // src/middlewares/dev-logs/health.controller.ts
2659
2810
  import http2 from "http";
@@ -3248,6 +3399,7 @@ function createDevLogRouter(options = {}) {
3248
3399
  router.get("/server-logs/stream", createSSEHandler(logDir));
3249
3400
  router.get("/trace/trigger/list", createGetTriggerListHandler(logDir));
3250
3401
  router.get("/trace/trigger/:instanceID", createGetTriggerDetailHandler(logDir));
3402
+ router.get("/trace/capability/list", createGetCapabilityTraceListHandler(logDir));
3251
3403
  router.get("/health", createHealthCheckHandler());
3252
3404
  return router;
3253
3405
  }
@@ -3306,17 +3458,17 @@ __name(createDevLogsMiddleware, "createDevLogsMiddleware");
3306
3458
  import express3 from "express";
3307
3459
 
3308
3460
  // src/middlewares/collect-logs/controller.ts
3309
- import { join as join6 } from "path";
3461
+ import { join as join7 } from "path";
3310
3462
  import fs11 from "fs";
3311
3463
 
3312
3464
  // src/middlewares/collect-logs/utils.ts
3313
- import { isAbsolute as isAbsolute2, join as join5 } from "path";
3465
+ import { isAbsolute as isAbsolute2, join as join6 } from "path";
3314
3466
  import fs10 from "fs";
3315
3467
  function resolveLogDir2(provided) {
3316
3468
  if (!provided) {
3317
- return join5(process.cwd(), "logs");
3469
+ return join6(process.cwd(), "logs");
3318
3470
  }
3319
- return isAbsolute2(provided) ? provided : join5(process.cwd(), provided);
3471
+ return isAbsolute2(provided) ? provided : join6(process.cwd(), provided);
3320
3472
  }
3321
3473
  __name(resolveLogDir2, "resolveLogDir");
3322
3474
  function ensureDir(dir) {
@@ -3339,7 +3491,7 @@ __name(serializeError2, "serializeError");
3339
3491
 
3340
3492
  // src/middlewares/collect-logs/controller.ts
3341
3493
  function collectLogsHandler(logDir, fileName) {
3342
- const filePath = join6(logDir, fileName);
3494
+ const filePath = join7(logDir, fileName);
3343
3495
  ensureDir(logDir);
3344
3496
  return async (req, res) => {
3345
3497
  try {
@@ -3364,7 +3516,7 @@ function collectLogsHandler(logDir, fileName) {
3364
3516
  }
3365
3517
  __name(collectLogsHandler, "collectLogsHandler");
3366
3518
  function collectLogsBatchHandler(logDir, fileName) {
3367
- const filePath = join6(logDir, fileName);
3519
+ const filePath = join7(logDir, fileName);
3368
3520
  ensureDir(logDir);
3369
3521
  return async (req, res) => {
3370
3522
  try {