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.
@@ -80,7 +80,7 @@ var init_constants = __esm({
80
80
  "packages/shared/dist/constants.js"() {
81
81
  "use strict";
82
82
  APP_NAME = "io";
83
- APP_VERSION = "4.1.2";
83
+ APP_VERSION = "4.1.4";
84
84
  API_PORT = 7777;
85
85
  API_HOST = "0.0.0.0";
86
86
  DEFAULT_MODEL = "gpt-4o";
@@ -2112,6 +2112,18 @@ var init_db = __esm({
2112
2112
  "CREATE INDEX IF NOT EXISTS idx_squad_instances_status ON squad_instances(status)",
2113
2113
  "CREATE INDEX IF NOT EXISTS idx_squad_instances_objective_id ON squad_instances(objective_id)"
2114
2114
  ]
2115
+ },
2116
+ {
2117
+ version: 4,
2118
+ name: "denormalize-usage-names",
2119
+ statements: [
2120
+ "ALTER TABLE token_usage ADD COLUMN squad_name TEXT",
2121
+ "ALTER TABLE token_usage ADD COLUMN agent_name TEXT",
2122
+ `UPDATE token_usage SET
2123
+ squad_name = (SELECT s.name FROM squads s WHERE s.id = token_usage.squad_id),
2124
+ agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
2125
+ WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
2126
+ ]
2115
2127
  }
2116
2128
  ];
2117
2129
  client = null;
@@ -2170,6 +2182,20 @@ async function getSquad(id, db) {
2170
2182
  ]);
2171
2183
  return { ...squad, members };
2172
2184
  }
2185
+ async function getSquadByName(name, db) {
2186
+ const database = db ?? await getDatabase();
2187
+ const result = await database.execute({
2188
+ sql: "SELECT * FROM squads WHERE name = ? LIMIT 1",
2189
+ args: [name]
2190
+ });
2191
+ const row = result.rows[0];
2192
+ if (!row) {
2193
+ return null;
2194
+ }
2195
+ const squad = mapSquad(row);
2196
+ const members = await getMembers(squad.id, database);
2197
+ return { ...squad, members };
2198
+ }
2173
2199
  async function listSquads(db) {
2174
2200
  const database = db ?? await getDatabase();
2175
2201
  const result = await database.execute("SELECT * FROM squads ORDER BY created_at DESC, id DESC");
@@ -11592,8 +11618,8 @@ var require_CronFileParser = __commonJS({
11592
11618
  * @throws If file cannot be read
11593
11619
  */
11594
11620
  static async parseFile(filePath) {
11595
- const { readFile: readFile10 } = await Promise.resolve().then(() => __importStar(__require("fs/promises")));
11596
- const data = await readFile10(filePath, "utf8");
11621
+ const { readFile: readFile11 } = await Promise.resolve().then(() => __importStar(__require("fs/promises")));
11622
+ const data = await readFile11(filePath, "utf8");
11597
11623
  return _CronFileParser.#parseContent(data);
11598
11624
  }
11599
11625
  /**
@@ -11862,8 +11888,8 @@ async function recordUsage(data, db) {
11862
11888
  createdAt: data.createdAt ?? nowIso()
11863
11889
  };
11864
11890
  await database.execute({
11865
- sql: `INSERT INTO token_usage (id, squad_id, agent_id, model, input_tokens, output_tokens, cost, premium_request_cost, token_unit_cost, created_at)
11866
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
11891
+ 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)
11892
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
11867
11893
  args: [
11868
11894
  usage.id,
11869
11895
  usage.squadId,
@@ -11874,6 +11900,8 @@ async function recordUsage(data, db) {
11874
11900
  usage.cost,
11875
11901
  data.premiumRequestCost ?? null,
11876
11902
  data.tokenUnitCost ?? null,
11903
+ data.squadName ?? null,
11904
+ data.agentName ?? null,
11877
11905
  usage.createdAt
11878
11906
  ]
11879
11907
  });
@@ -11938,8 +11966,8 @@ async function getUsageRecords(params = {}, db) {
11938
11966
  const result = await database.execute({
11939
11967
  sql: `SELECT tu.model, tu.input_tokens, tu.output_tokens, tu.cost,
11940
11968
  tu.created_at, tu.squad_id, tu.agent_id,
11941
- COALESCE(s.name, '') AS squad_name,
11942
- COALESCE(sm.name, '') AS agent_name
11969
+ COALESCE(s.name, tu.squad_name, '') AS squad_name,
11970
+ COALESCE(sm.name, tu.agent_name, '') AS agent_name
11943
11971
  FROM token_usage tu
11944
11972
  LEFT JOIN squads s ON s.id = tu.squad_id
11945
11973
  LEFT JOIN squad_members sm ON sm.id = tu.agent_id
@@ -31301,7 +31329,7 @@ var require_view = __commonJS({
31301
31329
  var dirname9 = path.dirname;
31302
31330
  var basename6 = path.basename;
31303
31331
  var extname4 = path.extname;
31304
- var join16 = path.join;
31332
+ var join17 = path.join;
31305
31333
  var resolve5 = path.resolve;
31306
31334
  module2.exports = View;
31307
31335
  function View(name, options2) {
@@ -31363,14 +31391,14 @@ var require_view = __commonJS({
31363
31391
  };
31364
31392
  View.prototype.resolve = function resolve6(dir, file2) {
31365
31393
  var ext = this.ext;
31366
- var path2 = join16(dir, file2);
31367
- var stat4 = tryStat(path2);
31368
- if (stat4 && stat4.isFile()) {
31394
+ var path2 = join17(dir, file2);
31395
+ var stat5 = tryStat(path2);
31396
+ if (stat5 && stat5.isFile()) {
31369
31397
  return path2;
31370
31398
  }
31371
- path2 = join16(dir, basename6(file2, ext), "index" + ext);
31372
- stat4 = tryStat(path2);
31373
- if (stat4 && stat4.isFile()) {
31399
+ path2 = join17(dir, basename6(file2, ext), "index" + ext);
31400
+ stat5 = tryStat(path2);
31401
+ if (stat5 && stat5.isFile()) {
31374
31402
  return path2;
31375
31403
  }
31376
31404
  };
@@ -31419,9 +31447,9 @@ var require_etag = __commonJS({
31419
31447
  }
31420
31448
  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";
31421
31449
  }
31422
- function stattag(stat4) {
31423
- var mtime = stat4.mtime.getTime().toString(16);
31424
- var size = stat4.size.toString(16);
31450
+ function stattag(stat5) {
31451
+ var mtime = stat5.mtime.getTime().toString(16);
31452
+ var size = stat5.size.toString(16);
31425
31453
  return '"' + size + "-" + mtime + '"';
31426
31454
  }
31427
31455
  }
@@ -35073,7 +35101,7 @@ var require_send = __commonJS({
35073
35101
  var Stream = __require("stream");
35074
35102
  var util = __require("util");
35075
35103
  var extname4 = path.extname;
35076
- var join16 = path.join;
35104
+ var join17 = path.join;
35077
35105
  var normalize = path.normalize;
35078
35106
  var resolve5 = path.resolve;
35079
35107
  var sep = path.sep;
@@ -35245,7 +35273,7 @@ var require_send = __commonJS({
35245
35273
  return res;
35246
35274
  }
35247
35275
  parts = path2.split(sep);
35248
- path2 = normalize(join16(root, path2));
35276
+ path2 = normalize(join17(root, path2));
35249
35277
  } else {
35250
35278
  if (UP_PATH_REGEXP.test(path2)) {
35251
35279
  debug('malicious path "%s"', path2);
@@ -35276,8 +35304,8 @@ var require_send = __commonJS({
35276
35304
  this.sendFile(path2);
35277
35305
  return res;
35278
35306
  };
35279
- SendStream.prototype.send = function send3(path2, stat4) {
35280
- var len = stat4.size;
35307
+ SendStream.prototype.send = function send3(path2, stat5) {
35308
+ var len = stat5.size;
35281
35309
  var options2 = this.options;
35282
35310
  var opts = {};
35283
35311
  var res = this.res;
@@ -35289,7 +35317,7 @@ var require_send = __commonJS({
35289
35317
  return;
35290
35318
  }
35291
35319
  debug('pipe "%s"', path2);
35292
- this.setHeader(path2, stat4);
35320
+ this.setHeader(path2, stat5);
35293
35321
  this.type(path2);
35294
35322
  if (this.isConditionalGET()) {
35295
35323
  if (this.isPreconditionFailure()) {
@@ -35345,16 +35373,16 @@ var require_send = __commonJS({
35345
35373
  var i = 0;
35346
35374
  var self = this;
35347
35375
  debug('stat "%s"', path2);
35348
- fs.stat(path2, function onstat(err, stat4) {
35376
+ fs.stat(path2, function onstat(err, stat5) {
35349
35377
  var pathEndsWithSep = path2[path2.length - 1] === sep;
35350
35378
  if (err && err.code === "ENOENT" && !extname4(path2) && !pathEndsWithSep) {
35351
35379
  return next(err);
35352
35380
  }
35353
35381
  if (err) return self.onStatError(err);
35354
- if (stat4.isDirectory()) return self.redirect(path2);
35382
+ if (stat5.isDirectory()) return self.redirect(path2);
35355
35383
  if (pathEndsWithSep) return self.error(404);
35356
- self.emit("file", path2, stat4);
35357
- self.send(path2, stat4);
35384
+ self.emit("file", path2, stat5);
35385
+ self.send(path2, stat5);
35358
35386
  });
35359
35387
  function next(err) {
35360
35388
  if (self._extensions.length <= i) {
@@ -35362,11 +35390,11 @@ var require_send = __commonJS({
35362
35390
  }
35363
35391
  var p = path2 + "." + self._extensions[i++];
35364
35392
  debug('stat "%s"', p);
35365
- fs.stat(p, function(err2, stat4) {
35393
+ fs.stat(p, function(err2, stat5) {
35366
35394
  if (err2) return next(err2);
35367
- if (stat4.isDirectory()) return next();
35368
- self.emit("file", p, stat4);
35369
- self.send(p, stat4);
35395
+ if (stat5.isDirectory()) return next();
35396
+ self.emit("file", p, stat5);
35397
+ self.send(p, stat5);
35370
35398
  });
35371
35399
  }
35372
35400
  };
@@ -35378,13 +35406,13 @@ var require_send = __commonJS({
35378
35406
  if (err) return self.onStatError(err);
35379
35407
  return self.error(404);
35380
35408
  }
35381
- var p = join16(path2, self._index[i]);
35409
+ var p = join17(path2, self._index[i]);
35382
35410
  debug('stat "%s"', p);
35383
- fs.stat(p, function(err2, stat4) {
35411
+ fs.stat(p, function(err2, stat5) {
35384
35412
  if (err2) return next(err2);
35385
- if (stat4.isDirectory()) return next();
35386
- self.emit("file", p, stat4);
35387
- self.send(p, stat4);
35413
+ if (stat5.isDirectory()) return next();
35414
+ self.emit("file", p, stat5);
35415
+ self.send(p, stat5);
35388
35416
  });
35389
35417
  }
35390
35418
  next();
@@ -35415,9 +35443,9 @@ var require_send = __commonJS({
35415
35443
  debug("content-type %s", type2);
35416
35444
  res.setHeader("Content-Type", type2);
35417
35445
  };
35418
- SendStream.prototype.setHeader = function setHeader(path2, stat4) {
35446
+ SendStream.prototype.setHeader = function setHeader(path2, stat5) {
35419
35447
  var res = this.res;
35420
- this.emit("headers", res, path2, stat4);
35448
+ this.emit("headers", res, path2, stat5);
35421
35449
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
35422
35450
  debug("accept ranges");
35423
35451
  res.setHeader("Accept-Ranges", "bytes");
@@ -35431,12 +35459,12 @@ var require_send = __commonJS({
35431
35459
  res.setHeader("Cache-Control", cacheControl);
35432
35460
  }
35433
35461
  if (this._lastModified && !res.getHeader("Last-Modified")) {
35434
- var modified = stat4.mtime.toUTCString();
35462
+ var modified = stat5.mtime.toUTCString();
35435
35463
  debug("modified %s", modified);
35436
35464
  res.setHeader("Last-Modified", modified);
35437
35465
  }
35438
35466
  if (this._etag && !res.getHeader("ETag")) {
35439
- var val = etag(stat4);
35467
+ var val = etag(stat5);
35440
35468
  debug("etag %s", val);
35441
35469
  res.setHeader("ETag", val);
35442
35470
  }
@@ -51851,7 +51879,7 @@ import { mkdir as mkdir3, readFile as readFile2, rm, writeFile as writeFile2 } f
51851
51879
  import { basename, extname, join as join3 } from "node:path";
51852
51880
  async function getSkillContent(skill) {
51853
51881
  if (!skill.entryFile) return "";
51854
- const filePath = join3(SKILLS_DIR, skill.directory, skill.entryFile);
51882
+ const filePath = join3(skill.directory, skill.entryFile);
51855
51883
  try {
51856
51884
  return await readFile2(filePath, "utf8");
51857
51885
  } catch {
@@ -51874,7 +51902,7 @@ async function buildSkillSummaries(skills) {
51874
51902
  activatedForOrchestrator: true,
51875
51903
  preview: extractPreview(content),
51876
51904
  description: extractDescription(content),
51877
- filePath: skill.entryFile ? join3(SKILLS_DIR, skill.directory, skill.entryFile) : join3(SKILLS_DIR, skill.directory)
51905
+ filePath: skill.entryFile ? join3(skill.directory, skill.entryFile) : skill.directory
51878
51906
  };
51879
51907
  })
51880
51908
  );
@@ -52154,7 +52182,7 @@ var init_skills = __esm({
52154
52182
  return;
52155
52183
  }
52156
52184
  const content = await getSkillContent(skill);
52157
- const filePath = skill.entryFile ? join3(SKILLS_DIR, skill.directory, skill.entryFile) : join3(SKILLS_DIR, skill.directory);
52185
+ const filePath = skill.entryFile ? join3(skill.directory, skill.entryFile) : skill.directory;
52158
52186
  res.status(200).json({ name: skill.slug, content, filePath });
52159
52187
  } catch (error51) {
52160
52188
  res.status(500).json({
@@ -52180,7 +52208,7 @@ var init_skills = __esm({
52180
52208
  res.status(400).json({ error: "content is required" });
52181
52209
  return;
52182
52210
  }
52183
- const filePath = join3(SKILLS_DIR, skill.directory, skill.entryFile);
52211
+ const filePath = join3(skill.directory, skill.entryFile);
52184
52212
  await writeFile2(filePath, content, "utf8");
52185
52213
  res.status(200).json({ name: skill.slug, content, filePath });
52186
52214
  } catch (error51) {
@@ -52381,10 +52409,10 @@ async function spawnInstance(input2) {
52381
52409
  async function startInstance(instanceId, repoPath, baseBranch) {
52382
52410
  const branchName = `squad/instance-${instanceId.slice(0, 8)}`;
52383
52411
  try {
52384
- const { exec: exec8 } = await import("node:child_process");
52385
- const { promisify: promisify8 } = await import("node:util");
52386
- const execAsync8 = promisify8(exec8);
52387
- await execAsync8(`git fetch origin && git pull origin ${baseBranch}`, {
52412
+ const { exec: exec9 } = await import("node:child_process");
52413
+ const { promisify: promisify9 } = await import("node:util");
52414
+ const execAsync9 = promisify9(exec9);
52415
+ await execAsync9(`git fetch origin && git pull origin ${baseBranch}`, {
52388
52416
  cwd: repoPath,
52389
52417
  maxBuffer: 10 * 1024 * 1024
52390
52418
  });
@@ -52537,6 +52565,9 @@ var init_instances2 = __esm({
52537
52565
  });
52538
52566
 
52539
52567
  // packages/daemon/src/api/routes/squads.ts
52568
+ async function resolveSquad(idOrName) {
52569
+ return await getSquad(idOrName) ?? await getSquadByName(idOrName);
52570
+ }
52540
52571
  async function listObjectivesForSquad(squadId) {
52541
52572
  const database = await getDatabase();
52542
52573
  const result = await database.execute({
@@ -52651,7 +52682,7 @@ var init_squads2 = __esm({
52651
52682
  });
52652
52683
  router7.get("/api/squads/:id", async (req, res) => {
52653
52684
  try {
52654
- const squad = await getSquad(req.params.id);
52685
+ const squad = await resolveSquad(req.params.id);
52655
52686
  if (!squad) {
52656
52687
  res.status(404).json({ error: "Squad not found" });
52657
52688
  return;
@@ -52717,7 +52748,7 @@ var init_squads2 = __esm({
52717
52748
  });
52718
52749
  router7.put("/api/squads/:id", async (req, res) => {
52719
52750
  try {
52720
- const existing = await getSquad(req.params.id);
52751
+ const existing = await resolveSquad(req.params.id);
52721
52752
  if (!existing) {
52722
52753
  res.status(404).json({ error: "Squad not found" });
52723
52754
  return;
@@ -52761,7 +52792,7 @@ var init_squads2 = __esm({
52761
52792
  });
52762
52793
  router7.delete("/api/squads/:id", async (req, res) => {
52763
52794
  try {
52764
- const existing = await getSquad(req.params.id);
52795
+ const existing = await resolveSquad(req.params.id);
52765
52796
  if (!existing) {
52766
52797
  res.status(404).json({ error: "Squad not found" });
52767
52798
  return;
@@ -52788,12 +52819,12 @@ var init_squads2 = __esm({
52788
52819
  });
52789
52820
  router7.get("/api/squads/:id/members", async (req, res) => {
52790
52821
  try {
52791
- const squad = await getSquad(req.params.id);
52822
+ const squad = await resolveSquad(req.params.id);
52792
52823
  if (!squad) {
52793
52824
  res.status(404).json({ error: "Squad not found" });
52794
52825
  return;
52795
52826
  }
52796
- res.status(200).json(await getMembers(req.params.id));
52827
+ res.status(200).json(await getMembers(squad.id));
52797
52828
  } catch (error51) {
52798
52829
  res.status(500).json({
52799
52830
  error: "Failed to list squad members",
@@ -52803,7 +52834,7 @@ var init_squads2 = __esm({
52803
52834
  });
52804
52835
  router7.post("/api/squads/:id/objectives", async (req, res) => {
52805
52836
  try {
52806
- const squad = await getSquad(req.params.id);
52837
+ const squad = await resolveSquad(req.params.id);
52807
52838
  if (!squad) {
52808
52839
  res.status(404).json({ error: "Squad not found" });
52809
52840
  return;
@@ -52830,12 +52861,12 @@ var init_squads2 = __esm({
52830
52861
  });
52831
52862
  router7.get("/api/squads/:id/objectives", async (req, res) => {
52832
52863
  try {
52833
- const squad = await getSquad(req.params.id);
52864
+ const squad = await resolveSquad(req.params.id);
52834
52865
  if (!squad) {
52835
52866
  res.status(404).json({ error: "Squad not found" });
52836
52867
  return;
52837
52868
  }
52838
- res.status(200).json(await listObjectivesForSquad(req.params.id));
52869
+ res.status(200).json(await listObjectivesForSquad(squad.id));
52839
52870
  } catch (error51) {
52840
52871
  res.status(500).json({
52841
52872
  error: "Failed to list squad objectives",
@@ -52843,6 +52874,57 @@ var init_squads2 = __esm({
52843
52874
  });
52844
52875
  }
52845
52876
  });
52877
+ router7.get("/api/squads/:id/history", async (req, res) => {
52878
+ try {
52879
+ const squad = await resolveSquad(req.params.id);
52880
+ if (!squad) {
52881
+ res.status(404).json({ error: "Squad not found" });
52882
+ return;
52883
+ }
52884
+ const limit = Math.min(Math.max(Number(req.query.limit) || 50, 1), 200);
52885
+ const offset = Math.max(Number(req.query.offset) || 0, 0);
52886
+ const items = await getSquadActivity(squad.id, limit, offset);
52887
+ res.status(200).json({ items, total: items.length < limit ? offset + items.length : -1 });
52888
+ } catch (error51) {
52889
+ res.status(500).json({
52890
+ error: "Failed to fetch squad history",
52891
+ details: error51 instanceof Error ? error51.message : "Unknown error"
52892
+ });
52893
+ }
52894
+ });
52895
+ router7.get("/api/squads/:id/history/:activityId", async (req, res) => {
52896
+ try {
52897
+ const squad = await resolveSquad(req.params.id);
52898
+ if (!squad) {
52899
+ res.status(404).json({ error: "Squad not found" });
52900
+ return;
52901
+ }
52902
+ const database = await getDatabase();
52903
+ const result = await database.execute({
52904
+ sql: "SELECT * FROM activity WHERE id = ? AND squad_id = ? LIMIT 1",
52905
+ args: [req.params.activityId, squad.id]
52906
+ });
52907
+ const row = result.rows[0];
52908
+ if (!row) {
52909
+ res.status(404).json({ error: "Activity not found" });
52910
+ return;
52911
+ }
52912
+ res.status(200).json({
52913
+ id: asString(row.id),
52914
+ squadId: asString(row.squad_id),
52915
+ objectiveId: asNullableString(row.objective_id),
52916
+ event: asString(row.event),
52917
+ description: asNullableString(row.description),
52918
+ metadata: row.metadata ? JSON.parse(asString(row.metadata)) : null,
52919
+ createdAt: asString(row.created_at)
52920
+ });
52921
+ } catch (error51) {
52922
+ res.status(500).json({
52923
+ error: "Failed to fetch activity detail",
52924
+ details: error51 instanceof Error ? error51.message : "Unknown error"
52925
+ });
52926
+ }
52927
+ });
52846
52928
  router7.get("/api/squads/:name/instances/:instanceId", async (req, res) => {
52847
52929
  try {
52848
52930
  const instance = await getInstance(req.params.instanceId);
@@ -54198,7 +54280,7 @@ var require_sonic_boom = __commonJS({
54198
54280
  if (!(this instanceof SonicBoom)) {
54199
54281
  return new SonicBoom(opts);
54200
54282
  }
54201
- let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir10, retryEAGAIN, fsync, contentMode, mode } = opts || {};
54283
+ let { fd, dest, minLength, maxLength, maxWrite, periodicFlush, sync, append = true, mkdir: mkdir11, retryEAGAIN, fsync, contentMode, mode } = opts || {};
54202
54284
  fd = fd || dest;
54203
54285
  this._len = 0;
54204
54286
  this.fd = -1;
@@ -54223,7 +54305,7 @@ var require_sonic_boom = __commonJS({
54223
54305
  this.append = append || false;
54224
54306
  this.mode = mode;
54225
54307
  this.retryEAGAIN = retryEAGAIN || (() => true);
54226
- this.mkdir = mkdir10 || false;
54308
+ this.mkdir = mkdir11 || false;
54227
54309
  let fsWriteSync;
54228
54310
  let fsWrite;
54229
54311
  if (contentMode === kContentModeBuffer) {
@@ -54941,7 +55023,7 @@ var require_thread_stream = __commonJS({
54941
55023
  var { version: version2 } = require_package();
54942
55024
  var { EventEmitter: EventEmitter2 } = __require("events");
54943
55025
  var { Worker } = __require("worker_threads");
54944
- var { join: join16 } = __require("path");
55026
+ var { join: join17 } = __require("path");
54945
55027
  var { pathToFileURL: pathToFileURL2 } = __require("url");
54946
55028
  var { wait } = require_wait();
54947
55029
  var {
@@ -54984,7 +55066,7 @@ var require_thread_stream = __commonJS({
54984
55066
  function createWorker(stream, opts) {
54985
55067
  const { filename, workerData } = opts;
54986
55068
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
54987
- const toExecute = bundlerOverrides["thread-stream-worker"] || join16(__dirname, "lib", "worker.js");
55069
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join17(__dirname, "lib", "worker.js");
54988
55070
  const worker = new Worker(toExecute, {
54989
55071
  ...opts.workerOpts,
54990
55072
  trackUnmanagedFds: false,
@@ -55387,7 +55469,7 @@ var require_transport = __commonJS({
55387
55469
  "use strict";
55388
55470
  var { createRequire } = __require("module");
55389
55471
  var getCallers = require_caller();
55390
- var { join: join16, isAbsolute: isAbsolute2, sep } = __require("node:path");
55472
+ var { join: join17, isAbsolute: isAbsolute2, sep } = __require("node:path");
55391
55473
  var sleep = require_atomic_sleep();
55392
55474
  var onExit = require_on_exit_leak_free();
55393
55475
  var ThreadStream = require_thread_stream();
@@ -55450,7 +55532,7 @@ var require_transport = __commonJS({
55450
55532
  throw new Error("only one of target or targets can be specified");
55451
55533
  }
55452
55534
  if (targets) {
55453
- target = bundlerOverrides["pino-worker"] || join16(__dirname, "worker.js");
55535
+ target = bundlerOverrides["pino-worker"] || join17(__dirname, "worker.js");
55454
55536
  options2.targets = targets.filter((dest) => dest.target).map((dest) => {
55455
55537
  return {
55456
55538
  ...dest,
@@ -55468,7 +55550,7 @@ var require_transport = __commonJS({
55468
55550
  });
55469
55551
  });
55470
55552
  } else if (pipeline) {
55471
- target = bundlerOverrides["pino-worker"] || join16(__dirname, "worker.js");
55553
+ target = bundlerOverrides["pino-worker"] || join17(__dirname, "worker.js");
55472
55554
  options2.pipelines = [pipeline.map((dest) => {
55473
55555
  return {
55474
55556
  ...dest,
@@ -55490,7 +55572,7 @@ var require_transport = __commonJS({
55490
55572
  return origin;
55491
55573
  }
55492
55574
  if (origin === "pino/file") {
55493
- return join16(__dirname, "..", "file.js");
55575
+ return join17(__dirname, "..", "file.js");
55494
55576
  }
55495
55577
  let fixTarget2;
55496
55578
  for (const filePath of callers) {
@@ -56479,7 +56561,7 @@ var require_safe_stable_stringify = __commonJS({
56479
56561
  return circularValue;
56480
56562
  }
56481
56563
  let res = "";
56482
- let join16 = ",";
56564
+ let join17 = ",";
56483
56565
  const originalIndentation = indentation;
56484
56566
  if (Array.isArray(value)) {
56485
56567
  if (value.length === 0) {
@@ -56493,7 +56575,7 @@ var require_safe_stable_stringify = __commonJS({
56493
56575
  indentation += spacer;
56494
56576
  res += `
56495
56577
  ${indentation}`;
56496
- join16 = `,
56578
+ join17 = `,
56497
56579
  ${indentation}`;
56498
56580
  }
56499
56581
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -56501,13 +56583,13 @@ ${indentation}`;
56501
56583
  for (; i < maximumValuesToStringify - 1; i++) {
56502
56584
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
56503
56585
  res += tmp2 !== void 0 ? tmp2 : "null";
56504
- res += join16;
56586
+ res += join17;
56505
56587
  }
56506
56588
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
56507
56589
  res += tmp !== void 0 ? tmp : "null";
56508
56590
  if (value.length - 1 > maximumBreadth) {
56509
56591
  const removedKeys = value.length - maximumBreadth - 1;
56510
- res += `${join16}"... ${getItemCount(removedKeys)} not stringified"`;
56592
+ res += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
56511
56593
  }
56512
56594
  if (spacer !== "") {
56513
56595
  res += `
@@ -56528,7 +56610,7 @@ ${originalIndentation}`;
56528
56610
  let separator = "";
56529
56611
  if (spacer !== "") {
56530
56612
  indentation += spacer;
56531
- join16 = `,
56613
+ join17 = `,
56532
56614
  ${indentation}`;
56533
56615
  whitespace = " ";
56534
56616
  }
@@ -56542,13 +56624,13 @@ ${indentation}`;
56542
56624
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
56543
56625
  if (tmp !== void 0) {
56544
56626
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
56545
- separator = join16;
56627
+ separator = join17;
56546
56628
  }
56547
56629
  }
56548
56630
  if (keyLength > maximumBreadth) {
56549
56631
  const removedKeys = keyLength - maximumBreadth;
56550
56632
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
56551
- separator = join16;
56633
+ separator = join17;
56552
56634
  }
56553
56635
  if (spacer !== "" && separator.length > 1) {
56554
56636
  res = `
@@ -56589,7 +56671,7 @@ ${originalIndentation}`;
56589
56671
  }
56590
56672
  const originalIndentation = indentation;
56591
56673
  let res = "";
56592
- let join16 = ",";
56674
+ let join17 = ",";
56593
56675
  if (Array.isArray(value)) {
56594
56676
  if (value.length === 0) {
56595
56677
  return "[]";
@@ -56602,7 +56684,7 @@ ${originalIndentation}`;
56602
56684
  indentation += spacer;
56603
56685
  res += `
56604
56686
  ${indentation}`;
56605
- join16 = `,
56687
+ join17 = `,
56606
56688
  ${indentation}`;
56607
56689
  }
56608
56690
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -56610,13 +56692,13 @@ ${indentation}`;
56610
56692
  for (; i < maximumValuesToStringify - 1; i++) {
56611
56693
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
56612
56694
  res += tmp2 !== void 0 ? tmp2 : "null";
56613
- res += join16;
56695
+ res += join17;
56614
56696
  }
56615
56697
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
56616
56698
  res += tmp !== void 0 ? tmp : "null";
56617
56699
  if (value.length - 1 > maximumBreadth) {
56618
56700
  const removedKeys = value.length - maximumBreadth - 1;
56619
- res += `${join16}"... ${getItemCount(removedKeys)} not stringified"`;
56701
+ res += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
56620
56702
  }
56621
56703
  if (spacer !== "") {
56622
56704
  res += `
@@ -56629,7 +56711,7 @@ ${originalIndentation}`;
56629
56711
  let whitespace = "";
56630
56712
  if (spacer !== "") {
56631
56713
  indentation += spacer;
56632
- join16 = `,
56714
+ join17 = `,
56633
56715
  ${indentation}`;
56634
56716
  whitespace = " ";
56635
56717
  }
@@ -56638,7 +56720,7 @@ ${indentation}`;
56638
56720
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
56639
56721
  if (tmp !== void 0) {
56640
56722
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
56641
- separator = join16;
56723
+ separator = join17;
56642
56724
  }
56643
56725
  }
56644
56726
  if (spacer !== "" && separator.length > 1) {
@@ -56696,20 +56778,20 @@ ${originalIndentation}`;
56696
56778
  indentation += spacer;
56697
56779
  let res2 = `
56698
56780
  ${indentation}`;
56699
- const join17 = `,
56781
+ const join18 = `,
56700
56782
  ${indentation}`;
56701
56783
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
56702
56784
  let i = 0;
56703
56785
  for (; i < maximumValuesToStringify - 1; i++) {
56704
56786
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
56705
56787
  res2 += tmp2 !== void 0 ? tmp2 : "null";
56706
- res2 += join17;
56788
+ res2 += join18;
56707
56789
  }
56708
56790
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
56709
56791
  res2 += tmp !== void 0 ? tmp : "null";
56710
56792
  if (value.length - 1 > maximumBreadth) {
56711
56793
  const removedKeys = value.length - maximumBreadth - 1;
56712
- res2 += `${join17}"... ${getItemCount(removedKeys)} not stringified"`;
56794
+ res2 += `${join18}"... ${getItemCount(removedKeys)} not stringified"`;
56713
56795
  }
56714
56796
  res2 += `
56715
56797
  ${originalIndentation}`;
@@ -56725,16 +56807,16 @@ ${originalIndentation}`;
56725
56807
  return '"[Object]"';
56726
56808
  }
56727
56809
  indentation += spacer;
56728
- const join16 = `,
56810
+ const join17 = `,
56729
56811
  ${indentation}`;
56730
56812
  let res = "";
56731
56813
  let separator = "";
56732
56814
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
56733
56815
  if (isTypedArrayWithEntries(value)) {
56734
- res += stringifyTypedArray(value, join16, maximumBreadth);
56816
+ res += stringifyTypedArray(value, join17, maximumBreadth);
56735
56817
  keys = keys.slice(value.length);
56736
56818
  maximumPropertiesToStringify -= value.length;
56737
- separator = join16;
56819
+ separator = join17;
56738
56820
  }
56739
56821
  if (deterministic) {
56740
56822
  keys = sort(keys, comparator);
@@ -56745,13 +56827,13 @@ ${indentation}`;
56745
56827
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
56746
56828
  if (tmp !== void 0) {
56747
56829
  res += `${separator}${strEscape(key2)}: ${tmp}`;
56748
- separator = join16;
56830
+ separator = join17;
56749
56831
  }
56750
56832
  }
56751
56833
  if (keyLength > maximumBreadth) {
56752
56834
  const removedKeys = keyLength - maximumBreadth;
56753
56835
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
56754
- separator = join16;
56836
+ separator = join17;
56755
56837
  }
56756
56838
  if (separator !== "") {
56757
56839
  res = `
@@ -63399,6 +63481,20 @@ async function deletePage(pagePath) {
63399
63481
  await rm4(filePath);
63400
63482
  await pruneEmptyDirectories(dirname3(filePath), getWikiPagesDir());
63401
63483
  }
63484
+ async function deleteDirectory(dirPath) {
63485
+ const normalizedDir = dirPath.replace(/[\\/]+/g, "/").replace(/^\/+|\/+$/g, "");
63486
+ if (!normalizedDir) {
63487
+ throw new Error("Directory path is required");
63488
+ }
63489
+ const wikiPagesDir = getWikiPagesDir();
63490
+ const resolvedDir = resolve(wikiPagesDir, ...normalizedDir.split("/"));
63491
+ const relativePath = relative(wikiPagesDir, resolvedDir);
63492
+ if (relativePath.startsWith("..") || relativePath === "") {
63493
+ throw new Error(`Invalid wiki directory path: ${dirPath}`);
63494
+ }
63495
+ await rm4(resolvedDir, { recursive: true });
63496
+ await pruneEmptyDirectories(dirname3(resolvedDir), wikiPagesDir);
63497
+ }
63402
63498
  async function collectMarkdownFiles(directory) {
63403
63499
  try {
63404
63500
  const entries = await readdir2(directory, { withFileTypes: true });
@@ -63774,6 +63870,23 @@ var init_wiki3 = __esm({
63774
63870
  });
63775
63871
  }
63776
63872
  });
63873
+ router9.delete("/api/wiki/directories/*dirPath", async (req, res) => {
63874
+ try {
63875
+ const dirPath = extractPagePath(req.params.dirPath);
63876
+ if (!dirPath) {
63877
+ res.status(400).json({ error: "Directory path is required" });
63878
+ return;
63879
+ }
63880
+ logger.debug({ dirPath }, "Wiki directory delete requested");
63881
+ await deleteDirectory(dirPath);
63882
+ eventBus.emit(EVENT_NAMES.WIKI_UPDATED, { path: dirPath, action: "deleted" });
63883
+ res.status(200).json({ deleted: true });
63884
+ } catch (error51) {
63885
+ const message2 = error51 instanceof Error ? error51.message : "Unknown error";
63886
+ const status = message2.includes("no such file or directory") ? 404 : 500;
63887
+ res.status(status).json({ error: "Failed to delete directory", details: message2 });
63888
+ }
63889
+ });
63777
63890
  router9.get("/api/wiki/search", async (req, res) => {
63778
63891
  try {
63779
63892
  const query = typeof req.query.q === "string" ? req.query.q.trim() : "";
@@ -69330,7 +69443,8 @@ function mergeUsage(target, usage) {
69330
69443
  target.models.push(usage.model);
69331
69444
  }
69332
69445
  }
69333
- async function persistUsage(member, usageEvents) {
69446
+ async function persistUsage(member, usageEvents, squadName) {
69447
+ const resolvedSquadName = squadName ?? (member.squadId ? (await getSquad(member.squadId))?.name : null) ?? null;
69334
69448
  for (const usage of usageEvents) {
69335
69449
  const model = usage.model;
69336
69450
  const pricing = await getModelPricing(model);
@@ -69343,7 +69457,9 @@ async function persistUsage(member, usageEvents) {
69343
69457
  ) : 0;
69344
69458
  await recordUsage({
69345
69459
  squadId: member.squadId,
69460
+ squadName: resolvedSquadName,
69346
69461
  agentId: member.id,
69462
+ agentName: member.name,
69347
69463
  model,
69348
69464
  inputTokens: usage.inputTokens ?? 0,
69349
69465
  outputTokens: usage.outputTokens ?? 0,
@@ -70269,7 +70385,11 @@ async function runGit2(command, cwd) {
70269
70385
  return stdout.trim();
70270
70386
  }
70271
70387
  async function resolveRepoPath(repoUrl, repoName) {
70388
+ const urlSegments = repoUrl.replace(/\.git$/i, "").split("/").filter(Boolean);
70389
+ const owner = urlSegments.at(-2) ?? "";
70390
+ const managedDir = owner && repoName ? join15(DATA_DIR, "repos", `${owner}--${repoName}`) : null;
70272
70391
  const candidates = [
70392
+ ...managedDir ? [managedDir] : [],
70273
70393
  process.cwd(),
70274
70394
  join15(process.cwd(), repoName),
70275
70395
  join15(process.cwd(), "repos", repoName),
@@ -70536,6 +70656,7 @@ var init_runner = __esm({
70536
70656
  "packages/daemon/src/execution/runner.ts"() {
70537
70657
  "use strict";
70538
70658
  init_dist();
70659
+ init_paths();
70539
70660
  init_event_bus();
70540
70661
  init_manager2();
70541
70662
  init_store2();
@@ -70787,6 +70908,18 @@ var init_hiring = __esm({
70787
70908
  });
70788
70909
 
70789
70910
  // packages/daemon/src/orchestrator/tools/squad.ts
70911
+ import { exec as exec8 } from "node:child_process";
70912
+ import { mkdir as mkdir10, readFile as readFile9, readdir as readdir6, stat as stat4 } from "node:fs/promises";
70913
+ import { join as join16 } from "node:path";
70914
+ import { promisify as promisify8 } from "node:util";
70915
+ async function pathExists2(path) {
70916
+ try {
70917
+ await stat4(path);
70918
+ return true;
70919
+ } catch {
70920
+ return false;
70921
+ }
70922
+ }
70790
70923
  function getDefaultSquadConfig(_config) {
70791
70924
  return {
70792
70925
  prMode: "draft-pr",
@@ -70794,12 +70927,108 @@ function getDefaultSquadConfig(_config) {
70794
70927
  maxRevisions: QA_MAX_REVISIONS
70795
70928
  };
70796
70929
  }
70797
- function buildRepoAnalysis(repoUrl) {
70930
+ async function buildRepoAnalysis(repoUrl) {
70798
70931
  const normalized = repoUrl.trim();
70799
- const name = normalized.split("/").filter(Boolean).at(-1)?.replace(/\.git$/iu, "") ?? normalized;
70800
- return `Repository URL: ${normalized}
70801
- Repository name: ${name}
70802
- Use the repository identity and any available conventions to propose a practical squad composition.`;
70932
+ const segments = normalized.replace(/\.git$/i, "").split("/").filter(Boolean);
70933
+ const owner = segments.at(-2) ?? "";
70934
+ const name = segments.at(-1) ?? normalized;
70935
+ const lines = [`Repository URL: ${normalized}`, `Repository name: ${name}`];
70936
+ if (!owner || !name) {
70937
+ lines.push(
70938
+ "Use the repository identity and any available conventions to propose a practical squad composition."
70939
+ );
70940
+ return lines.join("\n");
70941
+ }
70942
+ const repoDir = join16(DATA_DIR, "repos", `${owner}--${name}`);
70943
+ try {
70944
+ await mkdir10(join16(DATA_DIR, "repos"), { recursive: true });
70945
+ if (await pathExists2(join16(repoDir, ".git"))) {
70946
+ await execAsync8("git pull --ff-only", { cwd: repoDir, timeout: 3e4 }).catch(
70947
+ () => void 0
70948
+ );
70949
+ } else {
70950
+ await execAsync8(`git clone --depth 50 ${normalized} "${repoDir}"`, {
70951
+ timeout: 6e4
70952
+ });
70953
+ }
70954
+ } catch {
70955
+ lines.push("Unable to clone repository locally; falling back to basic analysis.");
70956
+ lines.push("Based on the repository name, propose roles that match common project patterns.");
70957
+ return lines.join("\n");
70958
+ }
70959
+ try {
70960
+ const rootEntries = await readdir6(repoDir, { withFileTypes: true });
70961
+ const rootFiles = rootEntries.filter((e) => e.isFile()).map((e) => e.name);
70962
+ const rootDirs = rootEntries.filter((e) => e.isDirectory() && e.name !== ".git").map((e) => e.name);
70963
+ if (rootFiles.length) lines.push(`Root files: ${rootFiles.join(", ")}`);
70964
+ if (rootDirs.length) lines.push(`Root directories: ${rootDirs.join(", ")}`);
70965
+ const manifestFiles = [
70966
+ "package.json",
70967
+ "Cargo.toml",
70968
+ "go.mod",
70969
+ "requirements.txt",
70970
+ "pyproject.toml",
70971
+ "Gemfile",
70972
+ "pom.xml",
70973
+ "build.gradle",
70974
+ "composer.json",
70975
+ "Makefile",
70976
+ "Dockerfile",
70977
+ "docker-compose.yml",
70978
+ "docker-compose.yaml",
70979
+ ".github/workflows"
70980
+ ];
70981
+ for (const manifest of manifestFiles) {
70982
+ const fullPath = join16(repoDir, manifest);
70983
+ try {
70984
+ const fileStat = await stat4(fullPath);
70985
+ if (fileStat.isFile()) {
70986
+ const content = await readFile9(fullPath, "utf8");
70987
+ lines.push(`
70988
+ --- ${manifest} ---
70989
+ ${content.slice(0, 3e3)}`);
70990
+ } else if (fileStat.isDirectory()) {
70991
+ const children = await readdir6(fullPath);
70992
+ lines.push(`
70993
+ --- ${manifest}/ ---
70994
+ ${children.join(", ")}`);
70995
+ }
70996
+ } catch {
70997
+ }
70998
+ }
70999
+ const srcDirs = rootDirs.filter(
71000
+ (d) => ["src", "lib", "app", "packages", "crates", "cmd", "internal"].includes(d)
71001
+ );
71002
+ for (const srcDir of srcDirs) {
71003
+ try {
71004
+ const srcEntries = await readdir6(join16(repoDir, srcDir), { withFileTypes: true });
71005
+ const srcFiles = srcEntries.filter((e) => e.isFile()).map((e) => e.name);
71006
+ const srcSubDirs = srcEntries.filter((e) => e.isDirectory()).map((e) => e.name);
71007
+ lines.push(`
71008
+ --- ${srcDir}/ ---`);
71009
+ if (srcSubDirs.length) lines.push(` Directories: ${srcSubDirs.join(", ")}`);
71010
+ if (srcFiles.length) lines.push(` Files: ${srcFiles.slice(0, 30).join(", ")}`);
71011
+ } catch {
71012
+ }
71013
+ }
71014
+ const readmeCandidates = ["README.md", "README.rst", "README.txt", "README"];
71015
+ for (const readme of readmeCandidates) {
71016
+ try {
71017
+ const content = await readFile9(join16(repoDir, readme), "utf8");
71018
+ lines.push(`
71019
+ --- ${readme} (excerpt) ---
71020
+ ${content.slice(0, 1500)}`);
71021
+ break;
71022
+ } catch {
71023
+ }
71024
+ }
71025
+ } catch {
71026
+ lines.push("Filesystem scan failed; using minimal info.");
71027
+ }
71028
+ lines.push(
71029
+ "\nBased on the above repository structure and contents, propose roles that match the project's actual technology stack and architecture."
71030
+ );
71031
+ return lines.join("\n");
70803
71032
  }
70804
71033
  function formatSquadList(squads) {
70805
71034
  if (squads.length === 0) {
@@ -70850,7 +71079,10 @@ function createSquadToolExecutor(config2) {
70850
71079
  switch (toolName) {
70851
71080
  case "hire_squad": {
70852
71081
  const { repoUrl } = hireSquadSchema.parse(rawArgs);
70853
- const composition = await proposeSquadComposition(repoUrl, buildRepoAnalysis(repoUrl));
71082
+ const composition = await proposeSquadComposition(
71083
+ repoUrl,
71084
+ await buildRepoAnalysis(repoUrl)
71085
+ );
70854
71086
  const result = await hireSquad(repoUrl, composition, getDefaultSquadConfig(config2));
70855
71087
  return {
70856
71088
  message: `Squad ready for ${repoUrl}.`,
@@ -70917,17 +71149,19 @@ function createSquadToolExecutor(config2) {
70917
71149
  }
70918
71150
  };
70919
71151
  }
70920
- var hireSquadSchema, squadIdSchema, delegateToSquadSchema, squadToolDefinitions;
71152
+ var execAsync8, hireSquadSchema, squadIdSchema, delegateToSquadSchema, squadToolDefinitions;
70921
71153
  var init_squad2 = __esm({
70922
71154
  "packages/daemon/src/orchestrator/tools/squad.ts"() {
70923
71155
  "use strict";
70924
71156
  init_dist();
71157
+ init_paths();
70925
71158
  init_zod();
70926
71159
  init_instances2();
70927
71160
  init_runner();
70928
71161
  init_hiring();
70929
71162
  init_manager2();
70930
71163
  init_store2();
71164
+ execAsync8 = promisify8(exec8);
70931
71165
  hireSquadSchema = external_exports.object({
70932
71166
  repoUrl: external_exports.string().trim().min(1)
70933
71167
  });
@@ -85097,7 +85331,7 @@ var init_index = __esm({
85097
85331
  init_dist();
85098
85332
  init_paths();
85099
85333
  init_data_dir();
85100
- import { readFile as readFile9, writeFile as writeFile8 } from "node:fs/promises";
85334
+ import { readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
85101
85335
  import { stdin as input, stdout as output } from "node:process";
85102
85336
  import { createInterface } from "node:readline/promises";
85103
85337
  function printHelp() {
@@ -85112,7 +85346,7 @@ Usage:
85112
85346
  }
85113
85347
  async function readExistingConfig() {
85114
85348
  try {
85115
- const existingConfig = await readFile9(CONFIG_PATH, "utf8");
85349
+ const existingConfig = await readFile10(CONFIG_PATH, "utf8");
85116
85350
  const parsedConfig = JSON.parse(existingConfig);
85117
85351
  if (parsedConfig === null || typeof parsedConfig !== "object" || Array.isArray(parsedConfig)) {
85118
85352
  throw new Error(`Invalid config file at ${CONFIG_PATH}: expected a JSON object`);