heyio 4.1.2 → 4.1.4

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.
@@ -79,7 +79,7 @@ var init_constants = __esm({
79
79
  "packages/shared/dist/constants.js"() {
80
80
  "use strict";
81
81
  APP_NAME = "io";
82
- APP_VERSION = "4.1.2";
82
+ APP_VERSION = "4.1.4";
83
83
  API_PORT = 7777;
84
84
  API_HOST = "0.0.0.0";
85
85
  DEFAULT_MODEL = "gpt-4o";
@@ -9207,8 +9207,8 @@ var require_CronFileParser = __commonJS({
9207
9207
  * @throws If file cannot be read
9208
9208
  */
9209
9209
  static async parseFile(filePath) {
9210
- const { readFile: readFile9 } = await Promise.resolve().then(() => __importStar(__require("fs/promises")));
9211
- const data = await readFile9(filePath, "utf8");
9210
+ const { readFile: readFile10 } = await Promise.resolve().then(() => __importStar(__require("fs/promises")));
9211
+ const data = await readFile10(filePath, "utf8");
9212
9212
  return _CronFileParser.#parseContent(data);
9213
9213
  }
9214
9214
  /**
@@ -28106,7 +28106,7 @@ var require_view = __commonJS({
28106
28106
  var dirname9 = path.dirname;
28107
28107
  var basename6 = path.basename;
28108
28108
  var extname4 = path.extname;
28109
- var join16 = path.join;
28109
+ var join17 = path.join;
28110
28110
  var resolve5 = path.resolve;
28111
28111
  module2.exports = View;
28112
28112
  function View(name, options2) {
@@ -28168,14 +28168,14 @@ var require_view = __commonJS({
28168
28168
  };
28169
28169
  View.prototype.resolve = function resolve6(dir, file2) {
28170
28170
  var ext = this.ext;
28171
- var path2 = join16(dir, file2);
28172
- var stat4 = tryStat(path2);
28173
- if (stat4 && stat4.isFile()) {
28171
+ var path2 = join17(dir, file2);
28172
+ var stat5 = tryStat(path2);
28173
+ if (stat5 && stat5.isFile()) {
28174
28174
  return path2;
28175
28175
  }
28176
- path2 = join16(dir, basename6(file2, ext), "index" + ext);
28177
- stat4 = tryStat(path2);
28178
- if (stat4 && stat4.isFile()) {
28176
+ path2 = join17(dir, basename6(file2, ext), "index" + ext);
28177
+ stat5 = tryStat(path2);
28178
+ if (stat5 && stat5.isFile()) {
28179
28179
  return path2;
28180
28180
  }
28181
28181
  };
@@ -28224,9 +28224,9 @@ var require_etag = __commonJS({
28224
28224
  }
28225
28225
  return obj && typeof obj === "object" && "ctime" in obj && toString.call(obj.ctime) === "[object Date]" && "mtime" in obj && toString.call(obj.mtime) === "[object Date]" && "ino" in obj && typeof obj.ino === "number" && "size" in obj && typeof obj.size === "number";
28226
28226
  }
28227
- function stattag(stat4) {
28228
- var mtime = stat4.mtime.getTime().toString(16);
28229
- var size = stat4.size.toString(16);
28227
+ function stattag(stat5) {
28228
+ var mtime = stat5.mtime.getTime().toString(16);
28229
+ var size = stat5.size.toString(16);
28230
28230
  return '"' + size + "-" + mtime + '"';
28231
28231
  }
28232
28232
  }
@@ -31878,7 +31878,7 @@ var require_send = __commonJS({
31878
31878
  var Stream = __require("stream");
31879
31879
  var util = __require("util");
31880
31880
  var extname4 = path.extname;
31881
- var join16 = path.join;
31881
+ var join17 = path.join;
31882
31882
  var normalize = path.normalize;
31883
31883
  var resolve5 = path.resolve;
31884
31884
  var sep = path.sep;
@@ -32050,7 +32050,7 @@ var require_send = __commonJS({
32050
32050
  return res;
32051
32051
  }
32052
32052
  parts = path2.split(sep);
32053
- path2 = normalize(join16(root, path2));
32053
+ path2 = normalize(join17(root, path2));
32054
32054
  } else {
32055
32055
  if (UP_PATH_REGEXP.test(path2)) {
32056
32056
  debug('malicious path "%s"', path2);
@@ -32081,8 +32081,8 @@ var require_send = __commonJS({
32081
32081
  this.sendFile(path2);
32082
32082
  return res;
32083
32083
  };
32084
- SendStream.prototype.send = function send3(path2, stat4) {
32085
- var len = stat4.size;
32084
+ SendStream.prototype.send = function send3(path2, stat5) {
32085
+ var len = stat5.size;
32086
32086
  var options2 = this.options;
32087
32087
  var opts = {};
32088
32088
  var res = this.res;
@@ -32094,7 +32094,7 @@ var require_send = __commonJS({
32094
32094
  return;
32095
32095
  }
32096
32096
  debug('pipe "%s"', path2);
32097
- this.setHeader(path2, stat4);
32097
+ this.setHeader(path2, stat5);
32098
32098
  this.type(path2);
32099
32099
  if (this.isConditionalGET()) {
32100
32100
  if (this.isPreconditionFailure()) {
@@ -32150,16 +32150,16 @@ var require_send = __commonJS({
32150
32150
  var i = 0;
32151
32151
  var self = this;
32152
32152
  debug('stat "%s"', path2);
32153
- fs.stat(path2, function onstat(err, stat4) {
32153
+ fs.stat(path2, function onstat(err, stat5) {
32154
32154
  var pathEndsWithSep = path2[path2.length - 1] === sep;
32155
32155
  if (err && err.code === "ENOENT" && !extname4(path2) && !pathEndsWithSep) {
32156
32156
  return next(err);
32157
32157
  }
32158
32158
  if (err) return self.onStatError(err);
32159
- if (stat4.isDirectory()) return self.redirect(path2);
32159
+ if (stat5.isDirectory()) return self.redirect(path2);
32160
32160
  if (pathEndsWithSep) return self.error(404);
32161
- self.emit("file", path2, stat4);
32162
- self.send(path2, stat4);
32161
+ self.emit("file", path2, stat5);
32162
+ self.send(path2, stat5);
32163
32163
  });
32164
32164
  function next(err) {
32165
32165
  if (self._extensions.length <= i) {
@@ -32167,11 +32167,11 @@ var require_send = __commonJS({
32167
32167
  }
32168
32168
  var p = path2 + "." + self._extensions[i++];
32169
32169
  debug('stat "%s"', p);
32170
- fs.stat(p, function(err2, stat4) {
32170
+ fs.stat(p, function(err2, stat5) {
32171
32171
  if (err2) return next(err2);
32172
- if (stat4.isDirectory()) return next();
32173
- self.emit("file", p, stat4);
32174
- self.send(p, stat4);
32172
+ if (stat5.isDirectory()) return next();
32173
+ self.emit("file", p, stat5);
32174
+ self.send(p, stat5);
32175
32175
  });
32176
32176
  }
32177
32177
  };
@@ -32183,13 +32183,13 @@ var require_send = __commonJS({
32183
32183
  if (err) return self.onStatError(err);
32184
32184
  return self.error(404);
32185
32185
  }
32186
- var p = join16(path2, self._index[i]);
32186
+ var p = join17(path2, self._index[i]);
32187
32187
  debug('stat "%s"', p);
32188
- fs.stat(p, function(err2, stat4) {
32188
+ fs.stat(p, function(err2, stat5) {
32189
32189
  if (err2) return next(err2);
32190
- if (stat4.isDirectory()) return next();
32191
- self.emit("file", p, stat4);
32192
- self.send(p, stat4);
32190
+ if (stat5.isDirectory()) return next();
32191
+ self.emit("file", p, stat5);
32192
+ self.send(p, stat5);
32193
32193
  });
32194
32194
  }
32195
32195
  next();
@@ -32220,9 +32220,9 @@ var require_send = __commonJS({
32220
32220
  debug("content-type %s", type2);
32221
32221
  res.setHeader("Content-Type", type2);
32222
32222
  };
32223
- SendStream.prototype.setHeader = function setHeader(path2, stat4) {
32223
+ SendStream.prototype.setHeader = function setHeader(path2, stat5) {
32224
32224
  var res = this.res;
32225
- this.emit("headers", res, path2, stat4);
32225
+ this.emit("headers", res, path2, stat5);
32226
32226
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
32227
32227
  debug("accept ranges");
32228
32228
  res.setHeader("Accept-Ranges", "bytes");
@@ -32236,12 +32236,12 @@ var require_send = __commonJS({
32236
32236
  res.setHeader("Cache-Control", cacheControl);
32237
32237
  }
32238
32238
  if (this._lastModified && !res.getHeader("Last-Modified")) {
32239
- var modified = stat4.mtime.toUTCString();
32239
+ var modified = stat5.mtime.toUTCString();
32240
32240
  debug("modified %s", modified);
32241
32241
  res.setHeader("Last-Modified", modified);
32242
32242
  }
32243
32243
  if (this._etag && !res.getHeader("ETag")) {
32244
- var val = etag(stat4);
32244
+ var val = etag(stat5);
32245
32245
  debug("etag %s", val);
32246
32246
  res.setHeader("ETag", val);
32247
32247
  }
@@ -49462,7 +49462,7 @@ var require_sonic_boom = __commonJS({
49462
49462
  if (!(this instanceof SonicBoom)) {
49463
49463
  return new SonicBoom(opts);
49464
49464
  }
49465
- let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir10, retryEAGAIN, fsync, contentMode, mode } = opts || {};
49465
+ let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir11, retryEAGAIN, fsync, contentMode, mode } = opts || {};
49466
49466
  fd = fd || dest;
49467
49467
  this._len = 0;
49468
49468
  this.fd = -1;
@@ -49487,7 +49487,7 @@ var require_sonic_boom = __commonJS({
49487
49487
  this.append = append || false;
49488
49488
  this.mode = mode;
49489
49489
  this.retryEAGAIN = retryEAGAIN || (() => true);
49490
- this.mkdir = mkdir10 || false;
49490
+ this.mkdir = mkdir11 || false;
49491
49491
  let fsWriteSync;
49492
49492
  let fsWrite;
49493
49493
  if (contentMode === kContentModeBuffer) {
@@ -50205,7 +50205,7 @@ var require_thread_stream = __commonJS({
50205
50205
  var { version: version2 } = require_package();
50206
50206
  var { EventEmitter: EventEmitter2 } = __require("events");
50207
50207
  var { Worker } = __require("worker_threads");
50208
- var { join: join16 } = __require("path");
50208
+ var { join: join17 } = __require("path");
50209
50209
  var { pathToFileURL: pathToFileURL2 } = __require("url");
50210
50210
  var { wait } = require_wait();
50211
50211
  var {
@@ -50248,7 +50248,7 @@ var require_thread_stream = __commonJS({
50248
50248
  function createWorker(stream, opts) {
50249
50249
  const { filename, workerData } = opts;
50250
50250
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
50251
- const toExecute = bundlerOverrides["thread-stream-worker"] || join16(__dirname, "lib", "worker.js");
50251
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join17(__dirname, "lib", "worker.js");
50252
50252
  const worker = new Worker(toExecute, {
50253
50253
  ...opts.workerOpts,
50254
50254
  trackUnmanagedFds: false,
@@ -50651,7 +50651,7 @@ var require_transport = __commonJS({
50651
50651
  "use strict";
50652
50652
  var { createRequire } = __require("module");
50653
50653
  var getCallers = require_caller();
50654
- var { join: join16, isAbsolute: isAbsolute2, sep } = __require("node:path");
50654
+ var { join: join17, isAbsolute: isAbsolute2, sep } = __require("node:path");
50655
50655
  var sleep = require_atomic_sleep();
50656
50656
  var onExit = require_on_exit_leak_free();
50657
50657
  var ThreadStream = require_thread_stream();
@@ -50714,7 +50714,7 @@ var require_transport = __commonJS({
50714
50714
  throw new Error("only one of target or targets can be specified");
50715
50715
  }
50716
50716
  if (targets) {
50717
- target = bundlerOverrides["pino-worker"] || join16(__dirname, "worker.js");
50717
+ target = bundlerOverrides["pino-worker"] || join17(__dirname, "worker.js");
50718
50718
  options2.targets = targets.filter((dest) => dest.target).map((dest) => {
50719
50719
  return {
50720
50720
  ...dest,
@@ -50732,7 +50732,7 @@ var require_transport = __commonJS({
50732
50732
  });
50733
50733
  });
50734
50734
  } else if (pipeline) {
50735
- target = bundlerOverrides["pino-worker"] || join16(__dirname, "worker.js");
50735
+ target = bundlerOverrides["pino-worker"] || join17(__dirname, "worker.js");
50736
50736
  options2.pipelines = [pipeline.map((dest) => {
50737
50737
  return {
50738
50738
  ...dest,
@@ -50754,7 +50754,7 @@ var require_transport = __commonJS({
50754
50754
  return origin;
50755
50755
  }
50756
50756
  if (origin === "pino/file") {
50757
- return join16(__dirname, "..", "file.js");
50757
+ return join17(__dirname, "..", "file.js");
50758
50758
  }
50759
50759
  let fixTarget2;
50760
50760
  for (const filePath of callers) {
@@ -51743,7 +51743,7 @@ var require_safe_stable_stringify = __commonJS({
51743
51743
  return circularValue;
51744
51744
  }
51745
51745
  let res = "";
51746
- let join16 = ",";
51746
+ let join17 = ",";
51747
51747
  const originalIndentation = indentation;
51748
51748
  if (Array.isArray(value)) {
51749
51749
  if (value.length === 0) {
@@ -51757,7 +51757,7 @@ var require_safe_stable_stringify = __commonJS({
51757
51757
  indentation += spacer;
51758
51758
  res += `
51759
51759
  ${indentation}`;
51760
- join16 = `,
51760
+ join17 = `,
51761
51761
  ${indentation}`;
51762
51762
  }
51763
51763
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -51765,13 +51765,13 @@ ${indentation}`;
51765
51765
  for (; i < maximumValuesToStringify - 1; i++) {
51766
51766
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
51767
51767
  res += tmp2 !== void 0 ? tmp2 : "null";
51768
- res += join16;
51768
+ res += join17;
51769
51769
  }
51770
51770
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
51771
51771
  res += tmp !== void 0 ? tmp : "null";
51772
51772
  if (value.length - 1 > maximumBreadth) {
51773
51773
  const removedKeys = value.length - maximumBreadth - 1;
51774
- res += `${join16}"... ${getItemCount(removedKeys)} not stringified"`;
51774
+ res += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
51775
51775
  }
51776
51776
  if (spacer !== "") {
51777
51777
  res += `
@@ -51792,7 +51792,7 @@ ${originalIndentation}`;
51792
51792
  let separator = "";
51793
51793
  if (spacer !== "") {
51794
51794
  indentation += spacer;
51795
- join16 = `,
51795
+ join17 = `,
51796
51796
  ${indentation}`;
51797
51797
  whitespace = " ";
51798
51798
  }
@@ -51806,13 +51806,13 @@ ${indentation}`;
51806
51806
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
51807
51807
  if (tmp !== void 0) {
51808
51808
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
51809
- separator = join16;
51809
+ separator = join17;
51810
51810
  }
51811
51811
  }
51812
51812
  if (keyLength > maximumBreadth) {
51813
51813
  const removedKeys = keyLength - maximumBreadth;
51814
51814
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
51815
- separator = join16;
51815
+ separator = join17;
51816
51816
  }
51817
51817
  if (spacer !== "" && separator.length > 1) {
51818
51818
  res = `
@@ -51853,7 +51853,7 @@ ${originalIndentation}`;
51853
51853
  }
51854
51854
  const originalIndentation = indentation;
51855
51855
  let res = "";
51856
- let join16 = ",";
51856
+ let join17 = ",";
51857
51857
  if (Array.isArray(value)) {
51858
51858
  if (value.length === 0) {
51859
51859
  return "[]";
@@ -51866,7 +51866,7 @@ ${originalIndentation}`;
51866
51866
  indentation += spacer;
51867
51867
  res += `
51868
51868
  ${indentation}`;
51869
- join16 = `,
51869
+ join17 = `,
51870
51870
  ${indentation}`;
51871
51871
  }
51872
51872
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -51874,13 +51874,13 @@ ${indentation}`;
51874
51874
  for (; i < maximumValuesToStringify - 1; i++) {
51875
51875
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
51876
51876
  res += tmp2 !== void 0 ? tmp2 : "null";
51877
- res += join16;
51877
+ res += join17;
51878
51878
  }
51879
51879
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
51880
51880
  res += tmp !== void 0 ? tmp : "null";
51881
51881
  if (value.length - 1 > maximumBreadth) {
51882
51882
  const removedKeys = value.length - maximumBreadth - 1;
51883
- res += `${join16}"... ${getItemCount(removedKeys)} not stringified"`;
51883
+ res += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
51884
51884
  }
51885
51885
  if (spacer !== "") {
51886
51886
  res += `
@@ -51893,7 +51893,7 @@ ${originalIndentation}`;
51893
51893
  let whitespace = "";
51894
51894
  if (spacer !== "") {
51895
51895
  indentation += spacer;
51896
- join16 = `,
51896
+ join17 = `,
51897
51897
  ${indentation}`;
51898
51898
  whitespace = " ";
51899
51899
  }
@@ -51902,7 +51902,7 @@ ${indentation}`;
51902
51902
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
51903
51903
  if (tmp !== void 0) {
51904
51904
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
51905
- separator = join16;
51905
+ separator = join17;
51906
51906
  }
51907
51907
  }
51908
51908
  if (spacer !== "" && separator.length > 1) {
@@ -51960,20 +51960,20 @@ ${originalIndentation}`;
51960
51960
  indentation += spacer;
51961
51961
  let res2 = `
51962
51962
  ${indentation}`;
51963
- const join17 = `,
51963
+ const join18 = `,
51964
51964
  ${indentation}`;
51965
51965
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
51966
51966
  let i = 0;
51967
51967
  for (; i < maximumValuesToStringify - 1; i++) {
51968
51968
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
51969
51969
  res2 += tmp2 !== void 0 ? tmp2 : "null";
51970
- res2 += join17;
51970
+ res2 += join18;
51971
51971
  }
51972
51972
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
51973
51973
  res2 += tmp !== void 0 ? tmp : "null";
51974
51974
  if (value.length - 1 > maximumBreadth) {
51975
51975
  const removedKeys = value.length - maximumBreadth - 1;
51976
- res2 += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
51976
+ res2 += `${join18}"... ${getItemCount(removedKeys)} not stringified"`;
51977
51977
  }
51978
51978
  res2 += `
51979
51979
  ${originalIndentation}`;
@@ -51989,16 +51989,16 @@ ${originalIndentation}`;
51989
51989
  return '"[Object]"';
51990
51990
  }
51991
51991
  indentation += spacer;
51992
- const join16 = `,
51992
+ const join17 = `,
51993
51993
  ${indentation}`;
51994
51994
  let res = "";
51995
51995
  let separator = "";
51996
51996
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
51997
51997
  if (isTypedArrayWithEntries(value)) {
51998
- res += stringifyTypedArray(value, join16, maximumBreadth);
51998
+ res += stringifyTypedArray(value, join17, maximumBreadth);
51999
51999
  keys = keys.slice(value.length);
52000
52000
  maximumPropertiesToStringify -= value.length;
52001
- separator = join16;
52001
+ separator = join17;
52002
52002
  }
52003
52003
  if (deterministic) {
52004
52004
  keys = sort(keys, comparator);
@@ -52009,13 +52009,13 @@ ${indentation}`;
52009
52009
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
52010
52010
  if (tmp !== void 0) {
52011
52011
  res += `${separator}${strEscape(key2)}: ${tmp}`;
52012
- separator = join16;
52012
+ separator = join17;
52013
52013
  }
52014
52014
  }
52015
52015
  if (keyLength > maximumBreadth) {
52016
52016
  const removedKeys = keyLength - maximumBreadth;
52017
52017
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
52018
- separator = join16;
52018
+ separator = join17;
52019
52019
  }
52020
52020
  if (separator !== "") {
52021
52021
  res = `
@@ -77118,6 +77118,18 @@ var MIGRATIONS = [
77118
77118
  "CREATE INDEX IF NOT EXISTS idx_squad_instances_status ON squad_instances(status)",
77119
77119
  "CREATE INDEX IF NOT EXISTS idx_squad_instances_objective_id ON squad_instances(objective_id)"
77120
77120
  ]
77121
+ },
77122
+ {
77123
+ version: 4,
77124
+ name: "denormalize-usage-names",
77125
+ statements: [
77126
+ "ALTER TABLE token_usage ADD COLUMN squad_name TEXT",
77127
+ "ALTER TABLE token_usage ADD COLUMN agent_name TEXT",
77128
+ `UPDATE token_usage SET
77129
+ squad_name = (SELECT s.name FROM squads s WHERE s.id = token_usage.squad_id),
77130
+ agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
77131
+ WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
77132
+ ]
77121
77133
  }
77122
77134
  ];
77123
77135
  var client = null;
@@ -77300,6 +77312,20 @@ async function getSquad(id, db) {
77300
77312
  ]);
77301
77313
  return { ...squad, members };
77302
77314
  }
77315
+ async function getSquadByName(name, db) {
77316
+ const database = db ?? await getDatabase();
77317
+ const result = await database.execute({
77318
+ sql: "SELECT * FROM squads WHERE name = ? LIMIT 1",
77319
+ args: [name]
77320
+ });
77321
+ const row = result.rows[0];
77322
+ if (!row) {
77323
+ return null;
77324
+ }
77325
+ const squad = mapSquad(row);
77326
+ const members = await getMembers(squad.id, database);
77327
+ return { ...squad, members };
77328
+ }
77303
77329
  async function listSquads(db) {
77304
77330
  const database = db ?? await getDatabase();
77305
77331
  const result = await database.execute("SELECT * FROM squads ORDER BY created_at DESC, id DESC");
@@ -77802,8 +77828,8 @@ async function recordUsage(data, db) {
77802
77828
  createdAt: data.createdAt ?? nowIso()
77803
77829
  };
77804
77830
  await database.execute({
77805
- sql: `INSERT INTO token_usage (id, squad_id, agent_id, model, input_tokens, output_tokens, cost, premium_request_cost, token_unit_cost, created_at)
77806
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
77831
+ sql: `INSERT INTO token_usage (id, squad_id, agent_id, model, input_tokens, output_tokens, cost, premium_request_cost, token_unit_cost, squad_name, agent_name, created_at)
77832
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
77807
77833
  args: [
77808
77834
  usage.id,
77809
77835
  usage.squadId,
@@ -77814,6 +77840,8 @@ async function recordUsage(data, db) {
77814
77840
  usage.cost,
77815
77841
  data.premiumRequestCost ?? null,
77816
77842
  data.tokenUnitCost ?? null,
77843
+ data.squadName ?? null,
77844
+ data.agentName ?? null,
77817
77845
  usage.createdAt
77818
77846
  ]
77819
77847
  });
@@ -77878,8 +77906,8 @@ async function getUsageRecords(params = {}, db) {
77878
77906
  const result = await database.execute({
77879
77907
  sql: `SELECT tu.model, tu.input_tokens, tu.output_tokens, tu.cost,
77880
77908
  tu.created_at, tu.squad_id, tu.agent_id,
77881
- COALESCE(s.name, '') AS squad_name,
77882
- COALESCE(sm.name, '') AS agent_name
77909
+ COALESCE(s.name, tu.squad_name, '') AS squad_name,
77910
+ COALESCE(sm.name, tu.agent_name, '') AS agent_name
77883
77911
  FROM token_usage tu
77884
77912
  LEFT JOIN squads s ON s.id = tu.squad_id
77885
77913
  LEFT JOIN squad_members sm ON sm.id = tu.agent_id
@@ -78818,7 +78846,7 @@ import { basename, extname, join as join2 } from "node:path";
78818
78846
  var router6 = (0, import_express6.Router)();
78819
78847
  async function getSkillContent(skill) {
78820
78848
  if (!skill.entryFile) return "";
78821
- const filePath = join2(SKILLS_DIR, skill.directory, skill.entryFile);
78849
+ const filePath = join2(skill.directory, skill.entryFile);
78822
78850
  try {
78823
78851
  return await readFile2(filePath, "utf8");
78824
78852
  } catch {
@@ -78841,7 +78869,7 @@ async function buildSkillSummaries(skills) {
78841
78869
  activatedForOrchestrator: true,
78842
78870
  preview: extractPreview(content),
78843
78871
  description: extractDescription(content),
78844
- filePath: skill.entryFile ? join2(SKILLS_DIR, skill.directory, skill.entryFile) : join2(SKILLS_DIR, skill.directory)
78872
+ filePath: skill.entryFile ? join2(skill.directory, skill.entryFile) : skill.directory
78845
78873
  };
78846
78874
  })
78847
78875
  );
@@ -78887,7 +78915,7 @@ router6.get("/api/skills/:name", async (req, res) => {
78887
78915
  return;
78888
78916
  }
78889
78917
  const content = await getSkillContent(skill);
78890
- const filePath = skill.entryFile ? join2(SKILLS_DIR, skill.directory, skill.entryFile) : join2(SKILLS_DIR, skill.directory);
78918
+ const filePath = skill.entryFile ? join2(skill.directory, skill.entryFile) : skill.directory;
78891
78919
  res.status(200).json({ name: skill.slug, content, filePath });
78892
78920
  } catch (error51) {
78893
78921
  res.status(500).json({
@@ -78913,7 +78941,7 @@ router6.put("/api/skills/:name", async (req, res) => {
78913
78941
  res.status(400).json({ error: "content is required" });
78914
78942
  return;
78915
78943
  }
78916
- const filePath = join2(SKILLS_DIR, skill.directory, skill.entryFile);
78944
+ const filePath = join2(skill.directory, skill.entryFile);
78917
78945
  await writeFile2(filePath, content, "utf8");
78918
78946
  res.status(200).json({ name: skill.slug, content, filePath });
78919
78947
  } catch (error51) {
@@ -79343,10 +79371,10 @@ async function spawnInstance(input) {
79343
79371
  async function startInstance(instanceId, repoPath, baseBranch) {
79344
79372
  const branchName = `squad/instance-${instanceId.slice(0, 8)}`;
79345
79373
  try {
79346
- const { exec: exec8 } = await import("node:child_process");
79347
- const { promisify: promisify8 } = await import("node:util");
79348
- const execAsync8 = promisify8(exec8);
79349
- await execAsync8(`git fetch origin && git pull origin ${baseBranch}`, {
79374
+ const { exec: exec9 } = await import("node:child_process");
79375
+ const { promisify: promisify9 } = await import("node:util");
79376
+ const execAsync9 = promisify9(exec9);
79377
+ await execAsync9(`git fetch origin && git pull origin ${baseBranch}`, {
79350
79378
  cwd: repoPath,
79351
79379
  maxBuffer: 10 * 1024 * 1024
79352
79380
  });
@@ -79494,6 +79522,9 @@ var DEFAULT_CONFIG = {
79494
79522
  mcpServers: [],
79495
79523
  maxRevisions: QA_MAX_REVISIONS
79496
79524
  };
79525
+ async function resolveSquad(idOrName) {
79526
+ return await getSquad(idOrName) ?? await getSquadByName(idOrName);
79527
+ }
79497
79528
  router7.get("/api/squads", async (_req, res) => {
79498
79529
  try {
79499
79530
  const squads = await listSquads();
@@ -79522,7 +79553,7 @@ router7.get("/api/squads", async (_req, res) => {
79522
79553
  });
79523
79554
  router7.get("/api/squads/:id", async (req, res) => {
79524
79555
  try {
79525
- const squad = await getSquad(req.params.id);
79556
+ const squad = await resolveSquad(req.params.id);
79526
79557
  if (!squad) {
79527
79558
  res.status(404).json({ error: "Squad not found" });
79528
79559
  return;
@@ -79588,7 +79619,7 @@ router7.post("/api/squads", async (req, res) => {
79588
79619
  });
79589
79620
  router7.put("/api/squads/:id", async (req, res) => {
79590
79621
  try {
79591
- const existing = await getSquad(req.params.id);
79622
+ const existing = await resolveSquad(req.params.id);
79592
79623
  if (!existing) {
79593
79624
  res.status(404).json({ error: "Squad not found" });
79594
79625
  return;
@@ -79632,7 +79663,7 @@ router7.put("/api/squads/:id", async (req, res) => {
79632
79663
  });
79633
79664
  router7.delete("/api/squads/:id", async (req, res) => {
79634
79665
  try {
79635
- const existing = await getSquad(req.params.id);
79666
+ const existing = await resolveSquad(req.params.id);
79636
79667
  if (!existing) {
79637
79668
  res.status(404).json({ error: "Squad not found" });
79638
79669
  return;
@@ -79659,12 +79690,12 @@ router7.delete("/api/squads/:id", async (req, res) => {
79659
79690
  });
79660
79691
  router7.get("/api/squads/:id/members", async (req, res) => {
79661
79692
  try {
79662
- const squad = await getSquad(req.params.id);
79693
+ const squad = await resolveSquad(req.params.id);
79663
79694
  if (!squad) {
79664
79695
  res.status(404).json({ error: "Squad not found" });
79665
79696
  return;
79666
79697
  }
79667
- res.status(200).json(await getMembers(req.params.id));
79698
+ res.status(200).json(await getMembers(squad.id));
79668
79699
  } catch (error51) {
79669
79700
  res.status(500).json({
79670
79701
  error: "Failed to list squad members",
@@ -79674,7 +79705,7 @@ router7.get("/api/squads/:id/members", async (req, res) => {
79674
79705
  });
79675
79706
  router7.post("/api/squads/:id/objectives", async (req, res) => {
79676
79707
  try {
79677
- const squad = await getSquad(req.params.id);
79708
+ const squad = await resolveSquad(req.params.id);
79678
79709
  if (!squad) {
79679
79710
  res.status(404).json({ error: "Squad not found" });
79680
79711
  return;
@@ -79701,12 +79732,12 @@ router7.post("/api/squads/:id/objectives", async (req, res) => {
79701
79732
  });
79702
79733
  router7.get("/api/squads/:id/objectives", async (req, res) => {
79703
79734
  try {
79704
- const squad = await getSquad(req.params.id);
79735
+ const squad = await resolveSquad(req.params.id);
79705
79736
  if (!squad) {
79706
79737
  res.status(404).json({ error: "Squad not found" });
79707
79738
  return;
79708
79739
  }
79709
- res.status(200).json(await listObjectivesForSquad(req.params.id));
79740
+ res.status(200).json(await listObjectivesForSquad(squad.id));
79710
79741
  } catch (error51) {
79711
79742
  res.status(500).json({
79712
79743
  error: "Failed to list squad objectives",
@@ -79770,6 +79801,57 @@ function parseRepoInfo(repoUrl, repoOwner, repoName) {
79770
79801
  function isValidationError2(error51) {
79771
79802
  return error51 instanceof Error && /repoUrl|config|Invalid URL/i.test(error51.message);
79772
79803
  }
79804
+ router7.get("/api/squads/:id/history", async (req, res) => {
79805
+ try {
79806
+ const squad = await resolveSquad(req.params.id);
79807
+ if (!squad) {
79808
+ res.status(404).json({ error: "Squad not found" });
79809
+ return;
79810
+ }
79811
+ const limit = Math.min(Math.max(Number(req.query.limit) || 50, 1), 200);
79812
+ const offset = Math.max(Number(req.query.offset) || 0, 0);
79813
+ const items = await getSquadActivity(squad.id, limit, offset);
79814
+ res.status(200).json({ items, total: items.length < limit ? offset + items.length : -1 });
79815
+ } catch (error51) {
79816
+ res.status(500).json({
79817
+ error: "Failed to fetch squad history",
79818
+ details: error51 instanceof Error ? error51.message : "Unknown error"
79819
+ });
79820
+ }
79821
+ });
79822
+ router7.get("/api/squads/:id/history/:activityId", async (req, res) => {
79823
+ try {
79824
+ const squad = await resolveSquad(req.params.id);
79825
+ if (!squad) {
79826
+ res.status(404).json({ error: "Squad not found" });
79827
+ return;
79828
+ }
79829
+ const database = await getDatabase();
79830
+ const result = await database.execute({
79831
+ sql: "SELECT * FROM activity WHERE id = ? AND squad_id = ? LIMIT 1",
79832
+ args: [req.params.activityId, squad.id]
79833
+ });
79834
+ const row = result.rows[0];
79835
+ if (!row) {
79836
+ res.status(404).json({ error: "Activity not found" });
79837
+ return;
79838
+ }
79839
+ res.status(200).json({
79840
+ id: asString(row.id),
79841
+ squadId: asString(row.squad_id),
79842
+ objectiveId: asNullableString(row.objective_id),
79843
+ event: asString(row.event),
79844
+ description: asNullableString(row.description),
79845
+ metadata: row.metadata ? JSON.parse(asString(row.metadata)) : null,
79846
+ createdAt: asString(row.created_at)
79847
+ });
79848
+ } catch (error51) {
79849
+ res.status(500).json({
79850
+ error: "Failed to fetch activity detail",
79851
+ details: error51 instanceof Error ? error51.message : "Unknown error"
79852
+ });
79853
+ }
79854
+ });
79773
79855
  router7.get("/api/squads/:name/instances/:instanceId", async (req, res) => {
79774
79856
  try {
79775
79857
  const instance = await getInstance(req.params.instanceId);
@@ -80014,6 +80096,20 @@ async function deletePage(pagePath) {
80014
80096
  await rm4(filePath);
80015
80097
  await pruneEmptyDirectories(dirname3(filePath), getWikiPagesDir());
80016
80098
  }
80099
+ async function deleteDirectory(dirPath) {
80100
+ const normalizedDir = dirPath.replace(/[\\/]+/g, "/").replace(/^\/+|\/+$/g, "");
80101
+ if (!normalizedDir) {
80102
+ throw new Error("Directory path is required");
80103
+ }
80104
+ const wikiPagesDir = getWikiPagesDir();
80105
+ const resolvedDir = resolve(wikiPagesDir, ...normalizedDir.split("/"));
80106
+ const relativePath = relative(wikiPagesDir, resolvedDir);
80107
+ if (relativePath.startsWith("..") || relativePath === "") {
80108
+ throw new Error(`Invalid wiki directory path: ${dirPath}`);
80109
+ }
80110
+ await rm4(resolvedDir, { recursive: true });
80111
+ await pruneEmptyDirectories(dirname3(resolvedDir), wikiPagesDir);
80112
+ }
80017
80113
  async function collectMarkdownFiles(directory) {
80018
80114
  try {
80019
80115
  const entries = await readdir2(directory, { withFileTypes: true });
@@ -80337,6 +80433,23 @@ router9.delete("/api/wiki/pages/*pagePath", async (req, res) => {
80337
80433
  });
80338
80434
  }
80339
80435
  });
80436
+ router9.delete("/api/wiki/directories/*dirPath", async (req, res) => {
80437
+ try {
80438
+ const dirPath = extractPagePath(req.params.dirPath);
80439
+ if (!dirPath) {
80440
+ res.status(400).json({ error: "Directory path is required" });
80441
+ return;
80442
+ }
80443
+ logger.debug({ dirPath }, "Wiki directory delete requested");
80444
+ await deleteDirectory(dirPath);
80445
+ eventBus.emit(EVENT_NAMES.WIKI_UPDATED, { path: dirPath, action: "deleted" });
80446
+ res.status(200).json({ deleted: true });
80447
+ } catch (error51) {
80448
+ const message2 = error51 instanceof Error ? error51.message : "Unknown error";
80449
+ const status = message2.includes("no such file or directory") ? 404 : 500;
80450
+ res.status(status).json({ error: "Failed to delete directory", details: message2 });
80451
+ }
80452
+ });
80340
80453
  router9.get("/api/wiki/search", async (req, res) => {
80341
80454
  try {
80342
80455
  const query = typeof req.query.q === "string" ? req.query.q.trim() : "";
@@ -81964,10 +82077,16 @@ var executeSkillsToolCall = async (toolName, rawArgs) => {
81964
82077
 
81965
82078
  // packages/daemon/src/orchestrator/tools/squad.ts
81966
82079
  init_dist();
82080
+ init_paths();
81967
82081
  init_zod();
82082
+ import { exec as exec8 } from "node:child_process";
82083
+ import { mkdir as mkdir10, readFile as readFile9, readdir as readdir6, stat as stat4 } from "node:fs/promises";
82084
+ import { join as join16 } from "node:path";
82085
+ import { promisify as promisify8 } from "node:util";
81968
82086
 
81969
82087
  // packages/daemon/src/execution/runner.ts
81970
82088
  init_dist();
82089
+ init_paths();
81971
82090
  import { exec as exec7 } from "node:child_process";
81972
82091
  import { access as access2 } from "node:fs/promises";
81973
82092
  import { basename as basename5, join as join15 } from "node:path";
@@ -82063,7 +82182,8 @@ function mergeUsage(target, usage) {
82063
82182
  target.models.push(usage.model);
82064
82183
  }
82065
82184
  }
82066
- async function persistUsage(member, usageEvents) {
82185
+ async function persistUsage(member, usageEvents, squadName) {
82186
+ const resolvedSquadName = squadName ?? (member.squadId ? (await getSquad(member.squadId))?.name : null) ?? null;
82067
82187
  for (const usage of usageEvents) {
82068
82188
  const model = usage.model;
82069
82189
  const pricing = await getModelPricing(model);
@@ -82076,7 +82196,9 @@ async function persistUsage(member, usageEvents) {
82076
82196
  ) : 0;
82077
82197
  await recordUsage({
82078
82198
  squadId: member.squadId,
82199
+ squadName: resolvedSquadName,
82079
82200
  agentId: member.id,
82201
+ agentName: member.name,
82080
82202
  model,
82081
82203
  inputTokens: usage.inputTokens ?? 0,
82082
82204
  outputTokens: usage.outputTokens ?? 0,
@@ -82940,7 +83062,11 @@ async function runGit2(command, cwd) {
82940
83062
  return stdout.trim();
82941
83063
  }
82942
83064
  async function resolveRepoPath(repoUrl, repoName) {
83065
+ const urlSegments = repoUrl.replace(/\.git$/i, "").split("/").filter(Boolean);
83066
+ const owner = urlSegments.at(-2) ?? "";
83067
+ const managedDir = owner && repoName ? join15(DATA_DIR, "repos", `${owner}--${repoName}`) : null;
82943
83068
  const candidates = [
83069
+ ...managedDir ? [managedDir] : [],
82944
83070
  process.cwd(),
82945
83071
  join15(process.cwd(), repoName),
82946
83072
  join15(process.cwd(), "repos", repoName),
@@ -83430,6 +83556,15 @@ Role: ${memberDefinition.description}`
83430
83556
  }
83431
83557
 
83432
83558
  // packages/daemon/src/orchestrator/tools/squad.ts
83559
+ var execAsync8 = promisify8(exec8);
83560
+ async function pathExists2(path) {
83561
+ try {
83562
+ await stat4(path);
83563
+ return true;
83564
+ } catch {
83565
+ return false;
83566
+ }
83567
+ }
83433
83568
  var hireSquadSchema = external_exports.object({
83434
83569
  repoUrl: external_exports.string().trim().min(1)
83435
83570
  });
@@ -83479,12 +83614,108 @@ function getDefaultSquadConfig(_config) {
83479
83614
  maxRevisions: QA_MAX_REVISIONS
83480
83615
  };
83481
83616
  }
83482
- function buildRepoAnalysis(repoUrl) {
83617
+ async function buildRepoAnalysis(repoUrl) {
83483
83618
  const normalized = repoUrl.trim();
83484
- const name = normalized.split("/").filter(Boolean).at(-1)?.replace(/\.git$/iu, "") ?? normalized;
83485
- return `Repository URL: ${normalized}
83486
- Repository name: ${name}
83487
- Use the repository identity and any available conventions to propose a practical squad composition.`;
83619
+ const segments = normalized.replace(/\.git$/i, "").split("/").filter(Boolean);
83620
+ const owner = segments.at(-2) ?? "";
83621
+ const name = segments.at(-1) ?? normalized;
83622
+ const lines = [`Repository URL: ${normalized}`, `Repository name: ${name}`];
83623
+ if (!owner || !name) {
83624
+ lines.push(
83625
+ "Use the repository identity and any available conventions to propose a practical squad composition."
83626
+ );
83627
+ return lines.join("\n");
83628
+ }
83629
+ const repoDir = join16(DATA_DIR, "repos", `${owner}--${name}`);
83630
+ try {
83631
+ await mkdir10(join16(DATA_DIR, "repos"), { recursive: true });
83632
+ if (await pathExists2(join16(repoDir, ".git"))) {
83633
+ await execAsync8("git pull --ff-only", { cwd: repoDir, timeout: 3e4 }).catch(
83634
+ () => void 0
83635
+ );
83636
+ } else {
83637
+ await execAsync8(`git clone --depth 50 ${normalized} "${repoDir}"`, {
83638
+ timeout: 6e4
83639
+ });
83640
+ }
83641
+ } catch {
83642
+ lines.push("Unable to clone repository locally; falling back to basic analysis.");
83643
+ lines.push("Based on the repository name, propose roles that match common project patterns.");
83644
+ return lines.join("\n");
83645
+ }
83646
+ try {
83647
+ const rootEntries = await readdir6(repoDir, { withFileTypes: true });
83648
+ const rootFiles = rootEntries.filter((e) => e.isFile()).map((e) => e.name);
83649
+ const rootDirs = rootEntries.filter((e) => e.isDirectory() && e.name !== ".git").map((e) => e.name);
83650
+ if (rootFiles.length) lines.push(`Root files: ${rootFiles.join(", ")}`);
83651
+ if (rootDirs.length) lines.push(`Root directories: ${rootDirs.join(", ")}`);
83652
+ const manifestFiles = [
83653
+ "package.json",
83654
+ "Cargo.toml",
83655
+ "go.mod",
83656
+ "requirements.txt",
83657
+ "pyproject.toml",
83658
+ "Gemfile",
83659
+ "pom.xml",
83660
+ "build.gradle",
83661
+ "composer.json",
83662
+ "Makefile",
83663
+ "Dockerfile",
83664
+ "docker-compose.yml",
83665
+ "docker-compose.yaml",
83666
+ ".github/workflows"
83667
+ ];
83668
+ for (const manifest of manifestFiles) {
83669
+ const fullPath = join16(repoDir, manifest);
83670
+ try {
83671
+ const fileStat = await stat4(fullPath);
83672
+ if (fileStat.isFile()) {
83673
+ const content = await readFile9(fullPath, "utf8");
83674
+ lines.push(`
83675
+ --- ${manifest} ---
83676
+ ${content.slice(0, 3e3)}`);
83677
+ } else if (fileStat.isDirectory()) {
83678
+ const children = await readdir6(fullPath);
83679
+ lines.push(`
83680
+ --- ${manifest}/ ---
83681
+ ${children.join(", ")}`);
83682
+ }
83683
+ } catch {
83684
+ }
83685
+ }
83686
+ const srcDirs = rootDirs.filter(
83687
+ (d) => ["src", "lib", "app", "packages", "crates", "cmd", "internal"].includes(d)
83688
+ );
83689
+ for (const srcDir of srcDirs) {
83690
+ try {
83691
+ const srcEntries = await readdir6(join16(repoDir, srcDir), { withFileTypes: true });
83692
+ const srcFiles = srcEntries.filter((e) => e.isFile()).map((e) => e.name);
83693
+ const srcSubDirs = srcEntries.filter((e) => e.isDirectory()).map((e) => e.name);
83694
+ lines.push(`
83695
+ --- ${srcDir}/ ---`);
83696
+ if (srcSubDirs.length) lines.push(` Directories: ${srcSubDirs.join(", ")}`);
83697
+ if (srcFiles.length) lines.push(` Files: ${srcFiles.slice(0, 30).join(", ")}`);
83698
+ } catch {
83699
+ }
83700
+ }
83701
+ const readmeCandidates = ["README.md", "README.rst", "README.txt", "README"];
83702
+ for (const readme of readmeCandidates) {
83703
+ try {
83704
+ const content = await readFile9(join16(repoDir, readme), "utf8");
83705
+ lines.push(`
83706
+ --- ${readme} (excerpt) ---
83707
+ ${content.slice(0, 1500)}`);
83708
+ break;
83709
+ } catch {
83710
+ }
83711
+ }
83712
+ } catch {
83713
+ lines.push("Filesystem scan failed; using minimal info.");
83714
+ }
83715
+ lines.push(
83716
+ "\nBased on the above repository structure and contents, propose roles that match the project's actual technology stack and architecture."
83717
+ );
83718
+ return lines.join("\n");
83488
83719
  }
83489
83720
  function formatSquadList(squads) {
83490
83721
  if (squads.length === 0) {
@@ -83535,7 +83766,10 @@ function createSquadToolExecutor(config2) {
83535
83766
  switch (toolName) {
83536
83767
  case "hire_squad": {
83537
83768
  const { repoUrl } = hireSquadSchema.parse(rawArgs);
83538
- const composition = await proposeSquadComposition(repoUrl, buildRepoAnalysis(repoUrl));
83769
+ const composition = await proposeSquadComposition(
83770
+ repoUrl,
83771
+ await buildRepoAnalysis(repoUrl)
83772
+ );
83539
83773
  const result = await hireSquad(repoUrl, composition, getDefaultSquadConfig(config2));
83540
83774
  return {
83541
83775
  message: `Squad ready for ${repoUrl}.`,