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.
package/dist/daemon/cli.js
CHANGED
|
@@ -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.
|
|
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:
|
|
11596
|
-
const data = await
|
|
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
|
|
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 =
|
|
31367
|
-
var
|
|
31368
|
-
if (
|
|
31394
|
+
var path2 = join17(dir, file2);
|
|
31395
|
+
var stat5 = tryStat(path2);
|
|
31396
|
+
if (stat5 && stat5.isFile()) {
|
|
31369
31397
|
return path2;
|
|
31370
31398
|
}
|
|
31371
|
-
path2 =
|
|
31372
|
-
|
|
31373
|
-
if (
|
|
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(
|
|
31423
|
-
var mtime =
|
|
31424
|
-
var size =
|
|
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
|
|
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(
|
|
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,
|
|
35280
|
-
var len =
|
|
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,
|
|
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,
|
|
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 (
|
|
35382
|
+
if (stat5.isDirectory()) return self.redirect(path2);
|
|
35355
35383
|
if (pathEndsWithSep) return self.error(404);
|
|
35356
|
-
self.emit("file", path2,
|
|
35357
|
-
self.send(path2,
|
|
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,
|
|
35393
|
+
fs.stat(p, function(err2, stat5) {
|
|
35366
35394
|
if (err2) return next(err2);
|
|
35367
|
-
if (
|
|
35368
|
-
self.emit("file", p,
|
|
35369
|
-
self.send(p,
|
|
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 =
|
|
35409
|
+
var p = join17(path2, self._index[i]);
|
|
35382
35410
|
debug('stat "%s"', p);
|
|
35383
|
-
fs.stat(p, function(err2,
|
|
35411
|
+
fs.stat(p, function(err2, stat5) {
|
|
35384
35412
|
if (err2) return next(err2);
|
|
35385
|
-
if (
|
|
35386
|
-
self.emit("file", p,
|
|
35387
|
-
self.send(p,
|
|
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,
|
|
35446
|
+
SendStream.prototype.setHeader = function setHeader(path2, stat5) {
|
|
35419
35447
|
var res = this.res;
|
|
35420
|
-
this.emit("headers", res, path2,
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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:
|
|
52385
|
-
const { promisify:
|
|
52386
|
-
const
|
|
52387
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
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:
|
|
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 =
|
|
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:
|
|
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"] ||
|
|
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:
|
|
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"] ||
|
|
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"] ||
|
|
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
|
|
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
|
|
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
|
-
|
|
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 +=
|
|
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 += `${
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 +=
|
|
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 += `${
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 +=
|
|
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 += `${
|
|
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
|
|
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,
|
|
56816
|
+
res += stringifyTypedArray(value, join17, maximumBreadth);
|
|
56735
56817
|
keys = keys.slice(value.length);
|
|
56736
56818
|
maximumPropertiesToStringify -= value.length;
|
|
56737
|
-
separator =
|
|
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 =
|
|
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 =
|
|
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
|
|
70800
|
-
|
|
70801
|
-
|
|
70802
|
-
|
|
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(
|
|
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
|
|
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
|
|
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`);
|