viben 1.2.6 → 1.2.8

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.
Files changed (3) hide show
  1. package/dist/index.cjs +203 -166
  2. package/dist/index.js +225 -188
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2165,7 +2165,7 @@ import os3__default, { homedir as homedir2, platform as platform2, type, release
2165
2165
  import * as path21 from "path";
2166
2166
  import path21__default, { join as join2, dirname as dirname2, basename as basename2, isAbsolute, resolve as resolve2, parse as parse$1, sep as sep2, delimiter, extname as extname2, relative as relative2 } from "path";
2167
2167
  import * as fs15 from "fs/promises";
2168
- import { readFile, mkdir as mkdir2, writeFile as writeFile2, readdir as readdir2, rm, appendFile, cp, stat, access as access2, constants, rename, unlink as unlink2, chmod, realpath } from "fs/promises";
2168
+ import { readFile, mkdir as mkdir2, writeFile as writeFile2, readdir as readdir2, rm, appendFile, cp, stat as stat2, access as access2, constants, rename, unlink as unlink2, chmod, realpath } from "fs/promises";
2169
2169
  import * as fs20 from "fs";
2170
2170
  import fs20__default, { existsSync as existsSync2, mkdirSync as mkdirSync2, statSync as statSync2, openSync as openSync2, readSync, closeSync as closeSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2, watch as watch2, rmSync as rmSync2, copyFileSync, renameSync, cpSync, appendFileSync as appendFileSync2, createWriteStream, writeSync } from "fs";
2171
2171
  import { parse, stringify } from "yaml";
@@ -3635,7 +3635,7 @@ var init_memory = __esm({
3635
3635
  };
3636
3636
  }
3637
3637
  const content = await readFile(memoryPath, "utf-8");
3638
- const stats = await stat(memoryPath);
3638
+ const stats = await stat2(memoryPath);
3639
3639
  return {
3640
3640
  agent_id,
3641
3641
  content,
@@ -3693,7 +3693,7 @@ var init_memory = __esm({
3693
3693
  return null;
3694
3694
  }
3695
3695
  const content = await readFile(logPath, "utf-8");
3696
- const stats = await stat(logPath);
3696
+ const stats = await stat2(logPath);
3697
3697
  const entries = this.parseDailyLog(content);
3698
3698
  return {
3699
3699
  date: dateStr,
@@ -3827,7 +3827,7 @@ var init_memory = __esm({
3827
3827
  for (const date of dates) {
3828
3828
  const logPath = join2(memoryDir, `${date}.md`);
3829
3829
  if (fileExists(logPath)) {
3830
- const stats = await stat(logPath);
3830
+ const stats = await stat2(logPath);
3831
3831
  totalSize += stats.size;
3832
3832
  }
3833
3833
  }
@@ -8680,7 +8680,7 @@ var init_service = __esm({
8680
8680
  const exactPath = join2(tasksDir, name);
8681
8681
  if (existsSync2(exactPath)) {
8682
8682
  try {
8683
- const stats = await stat(exactPath);
8683
+ const stats = await stat2(exactPath);
8684
8684
  if (stats.isDirectory()) {
8685
8685
  return exactPath;
8686
8686
  }
@@ -11950,27 +11950,38 @@ function getTraceStats(tree) {
11950
11950
  traverse(tree.root, 1);
11951
11951
  return { totalSpans, successSpans, errorSpans, maxDepth, operations };
11952
11952
  }
11953
- async function listTraces(baseDir, date) {
11953
+ async function listTraces(baseDir, date, options) {
11954
11954
  const tracesDir = path21.join(baseDir, "traces");
11955
11955
  const targetDate = date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
11956
11956
  const dateDir = path21.join(tracesDir, targetDate);
11957
- if (!fs20.existsSync(dateDir)) {
11957
+ try {
11958
+ await fs15.access(dateDir);
11959
+ } catch {
11958
11960
  return [];
11959
11961
  }
11960
- const files = fs20.readdirSync(dateDir);
11961
- const traces = [];
11962
- for (const file of files) {
11963
- if (!file.endsWith(".jsonl")) continue;
11964
- const filePath = path21.join(dateDir, file);
11965
- const stat12 = fs20.statSync(filePath);
11966
- traces.push({
11967
- traceId: file.replace(".jsonl", ""),
11968
- filePath,
11969
- size: stat12.size,
11970
- mtime: stat12.mtime
11971
- });
11972
- }
11962
+ const files = await fs15.readdir(dateDir);
11963
+ const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
11964
+ const statResults = await Promise.all(
11965
+ jsonlFiles.map(async (file) => {
11966
+ const filePath = path21.join(dateDir, file);
11967
+ try {
11968
+ const stat13 = await fs15.stat(filePath);
11969
+ return {
11970
+ traceId: file.replace(".jsonl", ""),
11971
+ filePath,
11972
+ size: stat13.size,
11973
+ mtime: stat13.mtime
11974
+ };
11975
+ } catch {
11976
+ return null;
11977
+ }
11978
+ })
11979
+ );
11980
+ const traces = statResults.filter((t) => t !== null);
11973
11981
  traces.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
11982
+ if (options?.limit && options.limit > 0) {
11983
+ return traces.slice(0, options.limit);
11984
+ }
11974
11985
  return traces;
11975
11986
  }
11976
11987
  function listTraceDates(baseDir) {
@@ -11981,6 +11992,29 @@ function listTraceDates(baseDir) {
11981
11992
  const dirs = fs20.readdirSync(tracesDir);
11982
11993
  return dirs.filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
11983
11994
  }
11995
+ async function readFirstSpan(filePath) {
11996
+ const fileStream = fs20.createReadStream(filePath, { encoding: "utf-8" });
11997
+ try {
11998
+ const rl = readline.createInterface({
11999
+ input: fileStream,
12000
+ crlfDelay: Infinity
12001
+ });
12002
+ for await (const line of rl) {
12003
+ if (line.trim()) {
12004
+ try {
12005
+ return JSON.parse(line);
12006
+ } catch {
12007
+ return null;
12008
+ }
12009
+ }
12010
+ }
12011
+ return null;
12012
+ } catch {
12013
+ return null;
12014
+ } finally {
12015
+ fileStream.destroy();
12016
+ }
12017
+ }
11984
12018
  var init_trace_viewer = __esm({
11985
12019
  "src/telemetry/trace-viewer.ts"() {
11986
12020
  }
@@ -12219,13 +12253,13 @@ function cleanOldTelemetryFiles(baseDir, retentionDays = 7) {
12219
12253
  for (const entry of entries) {
12220
12254
  const entryPath = path21.join(dir, entry.name);
12221
12255
  if (entry.isDirectory()) {
12222
- const stat12 = fs20.statSync(entryPath);
12223
- if (stat12.mtimeMs < cutoff) {
12256
+ const stat13 = fs20.statSync(entryPath);
12257
+ if (stat13.mtimeMs < cutoff) {
12224
12258
  fs20.rmSync(entryPath, { recursive: true });
12225
12259
  }
12226
12260
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
12227
- const stat12 = fs20.statSync(entryPath);
12228
- if (stat12.mtimeMs < cutoff) {
12261
+ const stat13 = fs20.statSync(entryPath);
12262
+ if (stat13.mtimeMs < cutoff) {
12229
12263
  fs20.unlinkSync(entryPath);
12230
12264
  }
12231
12265
  }
@@ -15795,7 +15829,7 @@ async function copyTemplateDir(srcRelativePath, destPath, options, createdFiles,
15795
15829
  for (const entry of entries) {
15796
15830
  const srcEntryPath = join2(srcPath, entry);
15797
15831
  const destEntryPath = join2(destPath, entry);
15798
- const entryStat = await stat(srcEntryPath);
15832
+ const entryStat = await stat2(srcEntryPath);
15799
15833
  if (entryStat.isDirectory()) {
15800
15834
  await copyTemplateDir(
15801
15835
  join2(srcRelativePath, entry),
@@ -16508,7 +16542,7 @@ var init_workspace = __esm({
16508
16542
  if (!config) {
16509
16543
  return null;
16510
16544
  }
16511
- const fileStat = await stat(configPath);
16545
+ const fileStat = await stat2(configPath);
16512
16546
  return {
16513
16547
  path: workspace_path,
16514
16548
  name: config.name || basename2(workspace_path),
@@ -23277,10 +23311,10 @@ var require_coerce = __commonJS2({
23277
23311
  var require_truncate = __commonJS2({
23278
23312
  "../../node_modules/.pnpm/semver@7.8.0/node_modules/semver/functions/truncate.js"(exports2, module2) {
23279
23313
  var parse7 = require_parse();
23280
- var constants3 = require_constants2();
23314
+ var constants4 = require_constants2();
23281
23315
  var SemVer = require_semver();
23282
23316
  var truncate2 = (version2, truncation, options) => {
23283
- if (!constants3.RELEASE_TYPES.includes(truncation)) {
23317
+ if (!constants4.RELEASE_TYPES.includes(truncation)) {
23284
23318
  return null;
23285
23319
  }
23286
23320
  const clonedVersion = cloneInputVersion(version2, options);
@@ -24273,7 +24307,7 @@ var require_subset = __commonJS2({
24273
24307
  var require_semver2 = __commonJS2({
24274
24308
  "../../node_modules/.pnpm/semver@7.8.0/node_modules/semver/index.js"(exports2, module2) {
24275
24309
  var internalRe = require_re();
24276
- var constants3 = require_constants2();
24310
+ var constants4 = require_constants2();
24277
24311
  var SemVer = require_semver();
24278
24312
  var identifiers = require_identifiers();
24279
24313
  var parse7 = require_parse();
@@ -24357,8 +24391,8 @@ var require_semver2 = __commonJS2({
24357
24391
  re: internalRe.re,
24358
24392
  src: internalRe.src,
24359
24393
  tokens: internalRe.t,
24360
- SEMVER_SPEC_VERSION: constants3.SEMVER_SPEC_VERSION,
24361
- RELEASE_TYPES: constants3.RELEASE_TYPES,
24394
+ SEMVER_SPEC_VERSION: constants4.SEMVER_SPEC_VERSION,
24395
+ RELEASE_TYPES: constants4.RELEASE_TYPES,
24362
24396
  compareIdentifiers: identifiers.compareIdentifiers,
24363
24397
  rcompareIdentifiers: identifiers.rcompareIdentifiers
24364
24398
  };
@@ -24518,14 +24552,14 @@ var require_utils2 = __commonJS2({
24518
24552
  });
24519
24553
  };
24520
24554
  function notifierExists(notifier, cb) {
24521
- return fs23.stat(notifier, function(err, stat12) {
24522
- if (!err) return cb(err, stat12.isFile());
24555
+ return fs23.stat(notifier, function(err, stat13) {
24556
+ if (!err) return cb(err, stat13.isFile());
24523
24557
  if (path24.extname(notifier)) {
24524
24558
  return cb(err, false);
24525
24559
  }
24526
- return fs23.stat(notifier + ".exe", function(err2, stat13) {
24560
+ return fs23.stat(notifier + ".exe", function(err2, stat14) {
24527
24561
  if (err2) return cb(err2, false);
24528
- cb(err2, stat13.isFile());
24562
+ cb(err2, stat14.isFile());
24529
24563
  });
24530
24564
  });
24531
24565
  }
@@ -24881,15 +24915,15 @@ var require_windows = __commonJS2({
24881
24915
  }
24882
24916
  return false;
24883
24917
  }
24884
- function checkStat(stat12, path24, options) {
24885
- if (!stat12.isSymbolicLink() && !stat12.isFile()) {
24918
+ function checkStat(stat13, path24, options) {
24919
+ if (!stat13.isSymbolicLink() && !stat13.isFile()) {
24886
24920
  return false;
24887
24921
  }
24888
24922
  return checkPathExt(path24, options);
24889
24923
  }
24890
24924
  function isexe(path24, options, cb) {
24891
- fs23.stat(path24, function(er, stat12) {
24892
- cb(er, er ? false : checkStat(stat12, path24, options));
24925
+ fs23.stat(path24, function(er, stat13) {
24926
+ cb(er, er ? false : checkStat(stat13, path24, options));
24893
24927
  });
24894
24928
  }
24895
24929
  function sync(path24, options) {
@@ -24903,20 +24937,20 @@ var require_mode = __commonJS2({
24903
24937
  isexe.sync = sync;
24904
24938
  var fs23 = __require2("fs");
24905
24939
  function isexe(path24, options, cb) {
24906
- fs23.stat(path24, function(er, stat12) {
24907
- cb(er, er ? false : checkStat(stat12, options));
24940
+ fs23.stat(path24, function(er, stat13) {
24941
+ cb(er, er ? false : checkStat(stat13, options));
24908
24942
  });
24909
24943
  }
24910
24944
  function sync(path24, options) {
24911
24945
  return checkStat(fs23.statSync(path24), options);
24912
24946
  }
24913
- function checkStat(stat12, options) {
24914
- return stat12.isFile() && checkMode(stat12, options);
24947
+ function checkStat(stat13, options) {
24948
+ return stat13.isFile() && checkMode(stat13, options);
24915
24949
  }
24916
- function checkMode(stat12, options) {
24917
- var mod2 = stat12.mode;
24918
- var uid = stat12.uid;
24919
- var gid = stat12.gid;
24950
+ function checkMode(stat13, options) {
24951
+ var mod2 = stat13.mode;
24952
+ var uid = stat13.uid;
24953
+ var gid = stat13.gid;
24920
24954
  var myUid = options.uid !== void 0 ? options.uid : process.getuid && process.getuid();
24921
24955
  var myGid = options.gid !== void 0 ? options.gid : process.getgid && process.getgid();
24922
24956
  var u = parseInt("100", 8);
@@ -37551,12 +37585,12 @@ var require_form_data = __commonJS2({
37551
37585
  if (value.end != void 0 && value.end != Infinity && value.start != void 0) {
37552
37586
  callback(null, value.end + 1 - (value.start ? value.start : 0));
37553
37587
  } else {
37554
- fs23.stat(value.path, function(err, stat12) {
37588
+ fs23.stat(value.path, function(err, stat13) {
37555
37589
  if (err) {
37556
37590
  callback(err);
37557
37591
  return;
37558
37592
  }
37559
- var fileSize = stat12.size - (value.start ? value.start : 0);
37593
+ var fileSize = stat13.size - (value.start ? value.start : 0);
37560
37594
  callback(null, fileSize);
37561
37595
  });
37562
37596
  }
@@ -132457,14 +132491,14 @@ var init_session_store = __esm({
132457
132491
  return [];
132458
132492
  }
132459
132493
  const entries = await readdir2(sessionsDir, { withFileTypes: true });
132494
+ const dirEntries = entries.filter((entry) => entry.isDirectory());
132495
+ const results = await Promise.allSettled(
132496
+ dirEntries.map((entry) => this.getSession(agentId, entry.name, agentDir))
132497
+ );
132460
132498
  const sessions2 = [];
132461
- for (const entry of entries) {
132462
- if (entry.isDirectory()) {
132463
- try {
132464
- const config = await this.getSession(agentId, entry.name, agentDir);
132465
- sessions2.push(config);
132466
- } catch {
132467
- }
132499
+ for (const result of results) {
132500
+ if (result.status === "fulfilled") {
132501
+ sessions2.push(result.value);
132468
132502
  }
132469
132503
  }
132470
132504
  sessions2.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
@@ -134862,10 +134896,10 @@ var init_service_manager = __esm({
134862
134896
  let position = statSync2(logPath).size;
134863
134897
  const watcher = watch2(logPath, (eventType) => {
134864
134898
  if (eventType === "change") {
134865
- const stat12 = statSync2(logPath);
134866
- if (stat12.size > position) {
134899
+ const stat13 = statSync2(logPath);
134900
+ if (stat13.size > position) {
134867
134901
  const fd = openSync2(logPath, "r");
134868
- const buffer = Buffer.alloc(stat12.size - position);
134902
+ const buffer = Buffer.alloc(stat13.size - position);
134869
134903
  readSync(fd, buffer, 0, buffer.length, position);
134870
134904
  closeSync2(fd);
134871
134905
  const newContent = buffer.toString("utf-8");
@@ -134873,7 +134907,7 @@ var init_service_manager = __esm({
134873
134907
  for (const line of lines) {
134874
134908
  onLine(line);
134875
134909
  }
134876
- position = stat12.size;
134910
+ position = stat13.size;
134877
134911
  }
134878
134912
  }
134879
134913
  });
@@ -138685,13 +138719,14 @@ var init_service3 = __esm({
138685
138719
  return [];
138686
138720
  }
138687
138721
  const entries = await readdir2(this.baseDir, { withFileTypes: true });
138722
+ const dirEntries = entries.filter((entry) => entry.isDirectory());
138723
+ const results = await Promise.allSettled(
138724
+ dirEntries.map((entry) => this.getGroupChat(entry.name))
138725
+ );
138688
138726
  const configs = [];
138689
- for (const entry of entries) {
138690
- if (entry.isDirectory()) {
138691
- const config = await this.getGroupChat(entry.name);
138692
- if (config) {
138693
- configs.push(config);
138694
- }
138727
+ for (const result of results) {
138728
+ if (result.status === "fulfilled" && result.value !== null) {
138729
+ configs.push(result.value);
138695
138730
  }
138696
138731
  }
138697
138732
  return configs.sort(
@@ -138822,7 +138857,7 @@ var init_service3 = __esm({
138822
138857
  return this.readYaml(configPath);
138823
138858
  }
138824
138859
  /**
138825
- * List sessions for a group chat
138860
+ * List all sessions for a group chat
138826
138861
  */
138827
138862
  async listSessions(groupChatId) {
138828
138863
  const sessionsDir = this.sessionsDir(groupChatId);
@@ -138830,13 +138865,14 @@ var init_service3 = __esm({
138830
138865
  return [];
138831
138866
  }
138832
138867
  const entries = await readdir2(sessionsDir, { withFileTypes: true });
138868
+ const dirEntries = entries.filter((entry) => entry.isDirectory());
138869
+ const results = await Promise.allSettled(
138870
+ dirEntries.map((entry) => this.getSession(groupChatId, entry.name))
138871
+ );
138833
138872
  const sessions2 = [];
138834
- for (const entry of entries) {
138835
- if (entry.isDirectory()) {
138836
- const session = await this.getSession(groupChatId, entry.name);
138837
- if (session) {
138838
- sessions2.push(session);
138839
- }
138873
+ for (const result of results) {
138874
+ if (result.status === "fulfilled" && result.value !== null) {
138875
+ sessions2.push(result.value);
138840
138876
  }
138841
138877
  }
138842
138878
  return sessions2.sort(
@@ -139140,7 +139176,7 @@ var init_service3 = __esm({
139140
139176
  const finalFilename = await this.generateUniqueFilename(filesDir, filename);
139141
139177
  const filePath = join2(filesDir, finalFilename);
139142
139178
  await writeFile2(filePath, data);
139143
- const stats = await stat(filePath);
139179
+ const stats = await stat2(filePath);
139144
139180
  const guessedMime = mimeType || this.guessMimeType(finalFilename) || "application/octet-stream";
139145
139181
  const fileInfo = {
139146
139182
  id: randomUUID(),
@@ -139170,7 +139206,7 @@ var init_service3 = __esm({
139170
139206
  for (const entry of entries) {
139171
139207
  if (entry.isFile()) {
139172
139208
  const filePath = join2(filesDir, entry.name);
139173
- const stats = await stat(filePath);
139209
+ const stats = await stat2(filePath);
139174
139210
  const mimeType = this.guessMimeType(entry.name) || "application/octet-stream";
139175
139211
  files.push({
139176
139212
  id: entry.name,
@@ -139217,7 +139253,7 @@ var init_service3 = __esm({
139217
139253
  if (!existsSync2(filePath)) {
139218
139254
  return null;
139219
139255
  }
139220
- const stats = await stat(filePath);
139256
+ const stats = await stat2(filePath);
139221
139257
  const mimeType = this.guessMimeType(safeFilename) || "application/octet-stream";
139222
139258
  return {
139223
139259
  id: safeFilename,
@@ -139267,7 +139303,7 @@ var init_service3 = __esm({
139267
139303
  const finalFilename = await this.generateUniqueFilename(picturesDir, filename);
139268
139304
  const filePath = join2(picturesDir, finalFilename);
139269
139305
  await writeFile2(filePath, data);
139270
- const stats = await stat(filePath);
139306
+ const stats = await stat2(filePath);
139271
139307
  const guessedMime = mimeType || this.guessMimeType(finalFilename) || "image/jpeg";
139272
139308
  const fileInfo = {
139273
139309
  id: randomUUID(),
@@ -139297,7 +139333,7 @@ var init_service3 = __esm({
139297
139333
  for (const entry of entries) {
139298
139334
  if (entry.isFile()) {
139299
139335
  const filePath = join2(picturesDir, entry.name);
139300
- const stats = await stat(filePath);
139336
+ const stats = await stat2(filePath);
139301
139337
  const mimeType = this.guessMimeType(entry.name) || "image/jpeg";
139302
139338
  pictures.push({
139303
139339
  id: entry.name,
@@ -139344,7 +139380,7 @@ var init_service3 = __esm({
139344
139380
  if (!existsSync2(filePath)) {
139345
139381
  return null;
139346
139382
  }
139347
- const stats = await stat(filePath);
139383
+ const stats = await stat2(filePath);
139348
139384
  const mimeType = this.guessMimeType(safeFilename) || "image/jpeg";
139349
139385
  return {
139350
139386
  id: safeFilename,
@@ -149020,7 +149056,7 @@ var startupConfig;
149020
149056
  var gatewayStartTime;
149021
149057
  var init_health = __esm({
149022
149058
  "src/gateway/routes/health.ts"() {
149023
- VERSION3 = "1.2.6";
149059
+ VERSION3 = "1.2.8";
149024
149060
  startupConfig = null;
149025
149061
  gatewayStartTime = Date.now();
149026
149062
  }
@@ -149038,15 +149074,19 @@ async function discoverClaudeCodeSessions(workspacePath) {
149038
149074
  if (!fs20.existsSync(sessionDir)) {
149039
149075
  return [];
149040
149076
  }
149041
- const sessions2 = [];
149042
149077
  const entries = await fs20.promises.readdir(sessionDir, { withFileTypes: true });
149043
- for (const entry of entries) {
149044
- if (entry.isFile() && entry.name.endsWith(".jsonl")) {
149045
- const sessionId = entry.name.replace(".jsonl", "");
149046
- const filePath = path21.join(sessionDir, entry.name);
149047
- const stats = await fs20.promises.stat(filePath);
149048
- const name = await readFirstUserMessage(filePath);
149049
- sessions2.push({
149078
+ const jsonlEntries = entries.filter(
149079
+ (entry) => entry.isFile() && entry.name.endsWith(".jsonl")
149080
+ );
149081
+ const sessionPromises = jsonlEntries.map(async (entry) => {
149082
+ const sessionId = entry.name.replace(".jsonl", "");
149083
+ const filePath = path21.join(sessionDir, entry.name);
149084
+ try {
149085
+ const [stats, name] = await Promise.all([
149086
+ fs20.promises.stat(filePath),
149087
+ readFirstUserMessage(filePath)
149088
+ ]);
149089
+ return {
149050
149090
  id: sessionId,
149051
149091
  executor_type: "CLAUDE_CODE",
149052
149092
  workspace_path: workspacePath,
@@ -149054,10 +149094,14 @@ async function discoverClaudeCodeSessions(workspacePath) {
149054
149094
  updated_at: stats.mtime.toISOString(),
149055
149095
  name,
149056
149096
  message_count: Math.floor(stats.size / 1024)
149057
- // Rough estimate
149058
- });
149097
+ };
149098
+ } catch {
149099
+ return null;
149059
149100
  }
149060
- }
149101
+ });
149102
+ const sessions2 = (await Promise.all(sessionPromises)).filter(
149103
+ (s) => s !== null
149104
+ );
149061
149105
  sessions2.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
149062
149106
  return sessions2;
149063
149107
  }
@@ -149707,8 +149751,8 @@ function registerExecutorRoutes(fastify2) {
149707
149751
  const entries = fs20.readdirSync(folderPath);
149708
149752
  for (const entry of entries) {
149709
149753
  const entryPath = path21.join(folderPath, entry);
149710
- const stat12 = fs20.statSync(entryPath);
149711
- if (stat12.isDirectory()) {
149754
+ const stat13 = fs20.statSync(entryPath);
149755
+ if (stat13.isDirectory()) {
149712
149756
  const skillMdPath = path21.join(entryPath, "skill.md");
149713
149757
  if (fs20.existsSync(skillMdPath)) {
149714
149758
  const skill = parseSkillMd2(skillMdPath);
@@ -149792,8 +149836,8 @@ function registerExecutorRoutes(fastify2) {
149792
149836
  const entries = fs20.readdirSync(folderPath);
149793
149837
  for (const entry of entries) {
149794
149838
  const fullPath = path21.join(folderPath, entry);
149795
- const stat12 = fs20.statSync(fullPath);
149796
- if (stat12.isFile() && entry.endsWith(".md")) {
149839
+ const stat13 = fs20.statSync(fullPath);
149840
+ if (stat13.isFile() && entry.endsWith(".md")) {
149797
149841
  try {
149798
149842
  const content = fs20.readFileSync(fullPath, "utf-8");
149799
149843
  subagents.push(parseSubagentMd(fullPath, content));
@@ -149859,8 +149903,8 @@ function registerExecutorRoutes(fastify2) {
149859
149903
  const namespaces = fs20.readdirSync(folderPath);
149860
149904
  for (const namespace of namespaces) {
149861
149905
  const namespacePath = path21.join(folderPath, namespace);
149862
- const stat12 = fs20.statSync(namespacePath);
149863
- if (stat12.isDirectory()) {
149906
+ const stat13 = fs20.statSync(namespacePath);
149907
+ if (stat13.isDirectory()) {
149864
149908
  try {
149865
149909
  const files = fs20.readdirSync(namespacePath);
149866
149910
  for (const file of files) {
@@ -149882,7 +149926,7 @@ function registerExecutorRoutes(fastify2) {
149882
149926
  }
149883
149927
  } catch {
149884
149928
  }
149885
- } else if (stat12.isFile() && namespace.endsWith(".md")) {
149929
+ } else if (stat13.isFile() && namespace.endsWith(".md")) {
149886
149930
  const name = namespace.replace(/\.md$/, "");
149887
149931
  try {
149888
149932
  const content = fs20.readFileSync(namespacePath, "utf-8");
@@ -149982,8 +150026,8 @@ function registerExecutorRoutes(fastify2) {
149982
150026
  const entries = fs20.readdirSync(folderPath);
149983
150027
  for (const entry of entries) {
149984
150028
  const fullPath = path21.join(folderPath, entry);
149985
- const stat12 = fs20.statSync(fullPath);
149986
- if (stat12.isFile() && entry.endsWith(".md")) {
150029
+ const stat13 = fs20.statSync(fullPath);
150030
+ if (stat13.isFile() && entry.endsWith(".md")) {
149987
150031
  try {
149988
150032
  const content = fs20.readFileSync(fullPath, "utf-8");
149989
150033
  prompts.push(parsePromptMd(fullPath, content));
@@ -150852,10 +150896,10 @@ function registerAgentRoutes(fastify2, state) {
150852
150896
  const authFile = join2(claudeDir, "config.json");
150853
150897
  if (existsSync2(authFile)) {
150854
150898
  try {
150855
- const stat12 = statSync2(authFile);
150899
+ const stat13 = statSync2(authFile);
150856
150900
  availability = {
150857
150901
  type: "LOGIN_DETECTED",
150858
- last_auth_timestamp: Math.floor(stat12.mtimeMs)
150902
+ last_auth_timestamp: Math.floor(stat13.mtimeMs)
150859
150903
  };
150860
150904
  } catch {
150861
150905
  availability = { type: "INSTALLATION_FOUND" };
@@ -150904,10 +150948,10 @@ function registerAgentRoutes(fastify2, state) {
150904
150948
  const openClawConfig = join2(openClawDir, "openclaw.json");
150905
150949
  if (existsSync2(openClawConfig)) {
150906
150950
  try {
150907
- const stat12 = statSync2(openClawConfig);
150951
+ const stat13 = statSync2(openClawConfig);
150908
150952
  availability = {
150909
150953
  type: "LOGIN_DETECTED",
150910
- last_auth_timestamp: Math.floor(stat12.mtimeMs)
150954
+ last_auth_timestamp: Math.floor(stat13.mtimeMs)
150911
150955
  };
150912
150956
  } catch {
150913
150957
  availability = { type: "INSTALLATION_FOUND" };
@@ -159567,22 +159611,27 @@ var init_workspaces = __esm({
159567
159611
  function getDefaultWorkspacePath() {
159568
159612
  return homedir2();
159569
159613
  }
159570
- function hasExecutorConfig(workspacePath, folders) {
159614
+ async function pathExists(path24) {
159615
+ try {
159616
+ await access2(path24, constants.F_OK);
159617
+ return true;
159618
+ } catch {
159619
+ return false;
159620
+ }
159621
+ }
159622
+ async function hasExecutorConfig(workspacePath, folders) {
159571
159623
  for (const folder of folders) {
159572
- if (existsSync2(join2(workspacePath, folder))) {
159624
+ if (await pathExists(join2(workspacePath, folder))) {
159573
159625
  return true;
159574
159626
  }
159575
159627
  }
159576
159628
  return false;
159577
159629
  }
159578
- function countClaudeCodeSessions(workspacePath) {
159630
+ async function countClaudeCodeSessions(workspacePath) {
159579
159631
  const encodedPath = workspacePath.replace(/\//g, "-");
159580
159632
  const sessionsDir = join2(homedir2(), ".claude", "projects", encodedPath);
159581
- if (!existsSync2(sessionsDir)) {
159582
- return 0;
159583
- }
159584
159633
  try {
159585
- const entries = readdirSync2(sessionsDir);
159634
+ const entries = await readdir2(sessionsDir);
159586
159635
  return entries.filter((e) => e.endsWith(".jsonl")).length;
159587
159636
  } catch {
159588
159637
  return 0;
@@ -159598,7 +159647,7 @@ function registerChatListRoutes(fastify2) {
159598
159647
  const items = [];
159599
159648
  if (includeGlobal) {
159600
159649
  const globalVibenPath = join2(globalPath, ".viben", "group-chats");
159601
- if (existsSync2(globalVibenPath)) {
159650
+ if (await pathExists(globalVibenPath)) {
159602
159651
  try {
159603
159652
  const globalService = new GroupChatService(globalVibenPath);
159604
159653
  const globalChats = await globalService.listGroupChats();
@@ -159626,7 +159675,7 @@ function registerChatListRoutes(fastify2) {
159626
159675
  }
159627
159676
  if (workspacePath !== globalPath) {
159628
159677
  const workspaceVibenPath = join2(workspacePath, ".viben", "group-chats");
159629
- if (existsSync2(workspaceVibenPath)) {
159678
+ if (await pathExists(workspaceVibenPath)) {
159630
159679
  try {
159631
159680
  const workspaceService = new GroupChatService(workspaceVibenPath);
159632
159681
  const workspaceChats = await workspaceService.listGroupChats();
@@ -159655,10 +159704,10 @@ function registerChatListRoutes(fastify2) {
159655
159704
  }
159656
159705
  }
159657
159706
  for (const executor of EXECUTOR_CONFIGS) {
159658
- const hasWorkspaceConfig = hasExecutorConfig(workspacePath, executor.folders);
159659
- const hasGlobalConfig = includeGlobal && hasExecutorConfig(globalPath, executor.folders);
159707
+ const hasWorkspaceConfig = await hasExecutorConfig(workspacePath, executor.folders);
159708
+ const hasGlobalConfig = includeGlobal && await hasExecutorConfig(globalPath, executor.folders);
159660
159709
  if (hasWorkspaceConfig || hasGlobalConfig) {
159661
- const sessionCount = executor.id === "CLAUDE_CODE" ? countClaudeCodeSessions(workspacePath) : 0;
159710
+ const sessionCount = executor.id === "CLAUDE_CODE" ? await countClaudeCodeSessions(workspacePath) : 0;
159662
159711
  items.push({
159663
159712
  id: executor.id,
159664
159713
  item_type: "executor",
@@ -159704,30 +159753,28 @@ function registerChatListRoutes(fastify2) {
159704
159753
  } catch {
159705
159754
  }
159706
159755
  const vibenAgentsDir = join2(workspacePath, ".viben", "agents");
159707
- if (existsSync2(vibenAgentsDir)) {
159708
- try {
159709
- const entries = readdirSync2(vibenAgentsDir, { withFileTypes: true });
159710
- for (const entry of entries) {
159711
- if (entry.isDirectory()) {
159712
- const agentId = entry.name;
159713
- if (!items.some((i) => i.id === agentId)) {
159714
- items.push({
159715
- id: agentId,
159716
- item_type: "agent",
159717
- name: entry.name,
159718
- source: "workspace",
159719
- workspace_path: workspacePath,
159720
- icon_type: "viben",
159721
- is_global: false,
159722
- metadata: {
159723
- agent_type: "viben"
159724
- }
159725
- });
159726
- }
159756
+ try {
159757
+ const entries = await readdir2(vibenAgentsDir, { withFileTypes: true });
159758
+ for (const entry of entries) {
159759
+ if (entry.isDirectory()) {
159760
+ const agentId = entry.name;
159761
+ if (!items.some((i) => i.id === agentId)) {
159762
+ items.push({
159763
+ id: agentId,
159764
+ item_type: "agent",
159765
+ name: entry.name,
159766
+ source: "workspace",
159767
+ workspace_path: workspacePath,
159768
+ icon_type: "viben",
159769
+ is_global: false,
159770
+ metadata: {
159771
+ agent_type: "viben"
159772
+ }
159773
+ });
159727
159774
  }
159728
159775
  }
159729
- } catch {
159730
159776
  }
159777
+ } catch {
159731
159778
  }
159732
159779
  items.sort((a, b) => {
159733
159780
  if (!a.last_active && !b.last_active) return 0;
@@ -162416,7 +162463,7 @@ function resolvePath(path24) {
162416
162463
  return resolve2(path24);
162417
162464
  }
162418
162465
  async function getFileEntry(filePath, name) {
162419
- const stats = await stat(filePath);
162466
+ const stats = await stat2(filePath);
162420
162467
  return {
162421
162468
  name,
162422
162469
  path: filePath,
@@ -162460,7 +162507,7 @@ function registerFileRoutes(fastify2) {
162460
162507
  return { error: `Path does not exist: ${dirPath}` };
162461
162508
  }
162462
162509
  try {
162463
- const stats = await stat(dirPath);
162510
+ const stats = await stat2(dirPath);
162464
162511
  if (!stats.isDirectory()) {
162465
162512
  reply.code(400);
162466
162513
  return { error: `Path is not a directory: ${dirPath}` };
@@ -162516,7 +162563,7 @@ function registerFileRoutes(fastify2) {
162516
162563
  return { error: `File does not exist: ${filePath}` };
162517
162564
  }
162518
162565
  try {
162519
- const stats = await stat(filePath);
162566
+ const stats = await stat2(filePath);
162520
162567
  if (!stats.isFile()) {
162521
162568
  reply.code(400);
162522
162569
  return { error: `Path is not a file: ${filePath}` };
@@ -162589,7 +162636,7 @@ function registerFileRoutes(fastify2) {
162589
162636
  }
162590
162637
  try {
162591
162638
  if (existsSync2(dirPath)) {
162592
- const stats = await stat(dirPath);
162639
+ const stats = await stat2(dirPath);
162593
162640
  if (stats.isDirectory()) {
162594
162641
  reply.code(409);
162595
162642
  return { error: `Directory already exists: ${dirPath}` };
@@ -162967,7 +163014,7 @@ function registerFileRoutes(fastify2) {
162967
163014
  }
162968
163015
  try {
162969
163016
  const currentPlatform = platform2();
162970
- const stats = await stat(filePath);
163017
+ const stats = await stat2(filePath);
162971
163018
  const targetPath = stats.isDirectory() ? filePath : dirname2(filePath);
162972
163019
  if (currentPlatform === "darwin") {
162973
163020
  const revealProcess = spawn("open", [targetPath], {
@@ -163008,16 +163055,7 @@ function registerTelemetryRoutes(fastify2) {
163008
163055
  fastify2.get("/api/telemetry/dates", async (_request, reply) => {
163009
163056
  try {
163010
163057
  const dates = listTraceDates(baseDir);
163011
- const result = await Promise.all(
163012
- dates.map(async (date) => {
163013
- const traces = await listTraces(baseDir, date);
163014
- return {
163015
- date,
163016
- count: traces.length,
163017
- totalSize: traces.reduce((sum, t) => sum + t.size, 0)
163018
- };
163019
- })
163020
- );
163058
+ const result = dates.map((date) => ({ date }));
163021
163059
  return reply.send(result);
163022
163060
  } catch (error) {
163023
163061
  return reply.status(500).send({
@@ -163030,27 +163068,26 @@ function registerTelemetryRoutes(fastify2) {
163030
163068
  "/api/telemetry/traces",
163031
163069
  async (request, reply) => {
163032
163070
  try {
163033
- const { date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], route } = request.query;
163034
- const traces = await listTraces(baseDir, date);
163035
- let filteredTraces = traces;
163071
+ const { date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], route, limit: limitStr } = request.query;
163072
+ const parsedLimit = limitStr ? parseInt(limitStr, 10) : 100;
163073
+ const limit = isNaN(parsedLimit) || parsedLimit <= 0 ? 100 : parsedLimit;
163074
+ let filteredTraces;
163036
163075
  if (route) {
163076
+ const traces = await listTraces(baseDir, date);
163037
163077
  filteredTraces = [];
163038
163078
  for (const t of traces) {
163039
- const filePath = path21.join(baseDir, "traces", date, `${t.traceId}.jsonl`);
163040
- try {
163041
- const spans = await loadTrace(filePath);
163042
- const matches = spans.some((span) => {
163043
- const httpTarget = span.attributes["http.target"];
163044
- const httpRoute = span.attributes["http.route"];
163045
- const httpUrl = span.attributes["http.url"];
163046
- return httpTarget?.includes(route) || httpRoute?.includes(route) || httpUrl?.includes(route);
163047
- });
163048
- if (matches) {
163049
- filteredTraces.push(t);
163050
- }
163051
- } catch {
163079
+ if (filteredTraces.length >= limit) break;
163080
+ const firstSpan = await readFirstSpan(t.filePath);
163081
+ if (!firstSpan) continue;
163082
+ const httpTarget = firstSpan.attributes["http.target"];
163083
+ const httpRoute = firstSpan.attributes["http.route"];
163084
+ const httpUrl = firstSpan.attributes["http.url"];
163085
+ if (httpTarget?.includes(route) || httpRoute?.includes(route) || httpUrl?.includes(route)) {
163086
+ filteredTraces.push(t);
163052
163087
  }
163053
163088
  }
163089
+ } else {
163090
+ filteredTraces = await listTraces(baseDir, date, { limit });
163054
163091
  }
163055
163092
  const result = filteredTraces.map((t) => ({
163056
163093
  traceId: t.traceId,
@@ -163388,7 +163425,7 @@ async function findSkillFiles(dirs) {
163388
163425
  if (entry.isDirectory()) {
163389
163426
  const skillPath = join2(dir, entry.name, "SKILL.md");
163390
163427
  try {
163391
- await stat(skillPath);
163428
+ await stat2(skillPath);
163392
163429
  files.push(skillPath);
163393
163430
  } catch {
163394
163431
  }
@@ -164844,7 +164881,7 @@ async function getSessionFromFile(filePath) {
164844
164881
  }
164845
164882
  try {
164846
164883
  const entries = await parseLogFile(filePath);
164847
- const stat12 = statSync2(filePath);
164884
+ const stat13 = statSync2(filePath);
164848
164885
  const runId = basename2(filePath, ".log");
164849
164886
  let serverId = "unknown";
164850
164887
  let serverName = "Unknown Server";
@@ -164865,13 +164902,13 @@ async function getSessionFromFile(filePath) {
164865
164902
  server_id: serverId,
164866
164903
  server_name: serverName,
164867
164904
  pid,
164868
- created_at: stat12.birthtime.toISOString(),
164869
- updated_at: stat12.mtime.toISOString(),
164905
+ created_at: stat13.birthtime.toISOString(),
164906
+ updated_at: stat13.mtime.toISOString(),
164870
164907
  ended_at: null,
164871
164908
  log_file: filePath,
164872
164909
  log_count: entries.length,
164873
164910
  error_count: errorCount,
164874
- started_at: stat12.birthtime.toISOString()
164911
+ started_at: stat13.birthtime.toISOString()
164875
164912
  };
164876
164913
  } catch {
164877
164914
  return null;
@@ -164886,8 +164923,8 @@ async function getLogSessions(serverId) {
164886
164923
  for (const file of files) {
164887
164924
  if (!file.endsWith(".log")) continue;
164888
164925
  const filePath = join2(logsDir, file);
164889
- const stat12 = statSync2(filePath);
164890
- if (!stat12.isFile()) continue;
164926
+ const stat13 = statSync2(filePath);
164927
+ if (!stat13.isFile()) continue;
164891
164928
  const session = await getSessionFromFile(filePath);
164892
164929
  if (session) {
164893
164930
  if (!serverId || session.server_id === serverId) {
@@ -165024,8 +165061,8 @@ function registerLogsRoutes(fastify2) {
165024
165061
  for (const file of files) {
165025
165062
  if (!file.endsWith(".jsonl")) continue;
165026
165063
  const filePath = join2(apiLogsDir, file);
165027
- const stat12 = statSync2(filePath);
165028
- if (!stat12.isFile()) continue;
165064
+ const stat13 = statSync2(filePath);
165065
+ if (!stat13.isFile()) continue;
165029
165066
  const runId = basename2(file, ".jsonl");
165030
165067
  const content = await readFile(filePath, "utf-8");
165031
165068
  const lines = content.split("\n").filter((l) => l.trim());
@@ -165172,8 +165209,8 @@ function isCacheValid() {
165172
165209
  return false;
165173
165210
  }
165174
165211
  try {
165175
- const stat12 = statSync2(cachePath);
165176
- const age = Date.now() - stat12.mtimeMs;
165212
+ const stat13 = statSync2(cachePath);
165213
+ const age = Date.now() - stat13.mtimeMs;
165177
165214
  return age < CACHE_TTL_MS2;
165178
165215
  } catch {
165179
165216
  return false;
@@ -165416,8 +165453,8 @@ function isCacheValid2() {
165416
165453
  return false;
165417
165454
  }
165418
165455
  try {
165419
- const stat12 = statSync2(cachePath);
165420
- const age = Date.now() - stat12.mtimeMs;
165456
+ const stat13 = statSync2(cachePath);
165457
+ const age = Date.now() - stat13.mtimeMs;
165421
165458
  return age < CACHE_TTL_MS3;
165422
165459
  } catch {
165423
165460
  return false;
@@ -165693,7 +165730,7 @@ async function getDirSize(dir) {
165693
165730
  for (const entry of entries) {
165694
165731
  const entryPath = join2(dir, entry.name);
165695
165732
  if (entry.isFile()) {
165696
- const stats = await stat(entryPath);
165733
+ const stats = await stat2(entryPath);
165697
165734
  size += stats.size;
165698
165735
  } else if (entry.isDirectory()) {
165699
165736
  size += await getDirSize(entryPath);
@@ -165723,7 +165760,7 @@ async function getLatestModTime(dir) {
165723
165760
  const entries = await readdir2(dir, { withFileTypes: true });
165724
165761
  for (const entry of entries) {
165725
165762
  const entryPath = join2(dir, entry.name);
165726
- const stats = await stat(entryPath);
165763
+ const stats = await stat2(entryPath);
165727
165764
  if (!latestTime || stats.mtime > latestTime) {
165728
165765
  latestTime = stats.mtime;
165729
165766
  }
@@ -165859,7 +165896,7 @@ async function readDirectory(dirPath) {
165859
165896
  }
165860
165897
  const entryPath = join2(dirPath, entry.name);
165861
165898
  try {
165862
- const stats = await stat(entryPath);
165899
+ const stats = await stat2(entryPath);
165863
165900
  files.push({
165864
165901
  name: entry.name,
165865
165902
  path: entryPath,
@@ -175246,8 +175283,8 @@ function serveStaticFile(page, requestedPath) {
175246
175283
  error: `File not found: ${relativePath}`
175247
175284
  };
175248
175285
  }
175249
- const stat12 = statSync2(resolvedPath);
175250
- if (!stat12.isFile()) {
175286
+ const stat13 = statSync2(resolvedPath);
175287
+ if (!stat13.isFile()) {
175251
175288
  return {
175252
175289
  success: false,
175253
175290
  error: `Not a file: ${relativePath}`
@@ -184271,7 +184308,7 @@ ${chalk22.bold("Telemetry \u7EDF\u8BA1")}:
184271
184308
  init_lib();
184272
184309
  init_update();
184273
184310
  var execAsync11 = promisify(exec);
184274
- var CURRENT_VERSION = "1.2.6";
184311
+ var CURRENT_VERSION = "1.2.8";
184275
184312
  var GITHUB_REPO2 = "LinXueyuanStdio/viben";
184276
184313
  var NPM_PACKAGE = "viben";
184277
184314
  function compareSemver(a, b) {
@@ -192899,7 +192936,7 @@ function registerCommands(program) {
192899
192936
  registerAccountCommand(program);
192900
192937
  registerAppCommand(program);
192901
192938
  }
192902
- var VERSION4 = "1.2.6";
192939
+ var VERSION4 = "1.2.8";
192903
192940
  function createProgram() {
192904
192941
  const program = new Command();
192905
192942
  program.name("viben").description("Viben - Agent Swarm \xD7 Code Evolution").version(VERSION4, "-v, --version", "Output the version number");