heyio 4.2.4 → 4.2.7
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.2.
|
|
83
|
+
APP_VERSION = "4.2.7";
|
|
84
84
|
API_PORT = 7777;
|
|
85
85
|
API_HOST = "0.0.0.0";
|
|
86
86
|
DEFAULT_MODEL = "gpt-4o";
|
|
@@ -2121,6 +2121,11 @@ var init_db = __esm({
|
|
|
2121
2121
|
agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
|
|
2122
2122
|
WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
|
|
2123
2123
|
]
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
version: 5,
|
|
2127
|
+
name: "add-squad-soft-delete",
|
|
2128
|
+
statements: ["ALTER TABLE squads ADD COLUMN deleted_at TEXT"]
|
|
2124
2129
|
}
|
|
2125
2130
|
];
|
|
2126
2131
|
client = null;
|
|
@@ -2144,7 +2149,8 @@ async function createSquad(data, db) {
|
|
|
2144
2149
|
status: data.status ?? "active",
|
|
2145
2150
|
config: data.config,
|
|
2146
2151
|
createdAt: timestamp,
|
|
2147
|
-
updatedAt: timestamp
|
|
2152
|
+
updatedAt: timestamp,
|
|
2153
|
+
deletedAt: null
|
|
2148
2154
|
};
|
|
2149
2155
|
await database.execute({
|
|
2150
2156
|
sql: `INSERT INTO squads (id, name, repo_url, repo_owner, repo_name, status, config, created_at, updated_at)
|
|
@@ -2166,7 +2172,7 @@ async function createSquad(data, db) {
|
|
|
2166
2172
|
async function getSquad(id, db) {
|
|
2167
2173
|
const database = db ?? await getDatabase();
|
|
2168
2174
|
const squadResult = await database.execute({
|
|
2169
|
-
sql: "SELECT * FROM squads WHERE id = ? LIMIT 1",
|
|
2175
|
+
sql: "SELECT * FROM squads WHERE id = ? AND deleted_at IS NULL LIMIT 1",
|
|
2170
2176
|
args: [id]
|
|
2171
2177
|
});
|
|
2172
2178
|
const row = squadResult.rows[0];
|
|
@@ -2182,7 +2188,7 @@ async function getSquad(id, db) {
|
|
|
2182
2188
|
async function getSquadByName(name, db) {
|
|
2183
2189
|
const database = db ?? await getDatabase();
|
|
2184
2190
|
const result = await database.execute({
|
|
2185
|
-
sql: "SELECT * FROM squads WHERE name = ? LIMIT 1",
|
|
2191
|
+
sql: "SELECT * FROM squads WHERE name = ? AND deleted_at IS NULL LIMIT 1",
|
|
2186
2192
|
args: [name]
|
|
2187
2193
|
});
|
|
2188
2194
|
const row = result.rows[0];
|
|
@@ -2195,7 +2201,9 @@ async function getSquadByName(name, db) {
|
|
|
2195
2201
|
}
|
|
2196
2202
|
async function listSquads(db) {
|
|
2197
2203
|
const database = db ?? await getDatabase();
|
|
2198
|
-
const result = await database.execute(
|
|
2204
|
+
const result = await database.execute(
|
|
2205
|
+
"SELECT * FROM squads WHERE deleted_at IS NULL ORDER BY created_at DESC, id DESC"
|
|
2206
|
+
);
|
|
2199
2207
|
return result.rows.map((row) => mapSquad(row));
|
|
2200
2208
|
}
|
|
2201
2209
|
async function updateSquad(id, data, db) {
|
|
@@ -2214,7 +2222,8 @@ async function updateSquad(id, data, db) {
|
|
|
2214
2222
|
status: data.status ?? existing.status,
|
|
2215
2223
|
config: data.config ?? existing.config,
|
|
2216
2224
|
createdAt: existing.createdAt,
|
|
2217
|
-
updatedAt
|
|
2225
|
+
updatedAt,
|
|
2226
|
+
deletedAt: existing.deletedAt
|
|
2218
2227
|
};
|
|
2219
2228
|
await database.execute({
|
|
2220
2229
|
sql: `UPDATE squads
|
|
@@ -2235,16 +2244,34 @@ async function updateSquad(id, data, db) {
|
|
|
2235
2244
|
}
|
|
2236
2245
|
async function deleteSquad(id, db) {
|
|
2237
2246
|
const database = db ?? await getDatabase();
|
|
2247
|
+
const now = nowIso();
|
|
2238
2248
|
const result = await database.execute({
|
|
2239
|
-
sql: "
|
|
2240
|
-
args: [id]
|
|
2249
|
+
sql: "UPDATE squads SET status = 'deleted', deleted_at = ?, updated_at = ? WHERE id = ? AND deleted_at IS NULL",
|
|
2250
|
+
args: [now, now, id]
|
|
2241
2251
|
});
|
|
2242
2252
|
return result.rowsAffected > 0;
|
|
2243
2253
|
}
|
|
2254
|
+
async function restoreSquad(id, db) {
|
|
2255
|
+
const database = db ?? await getDatabase();
|
|
2256
|
+
const now = nowIso();
|
|
2257
|
+
const result = await database.execute({
|
|
2258
|
+
sql: "UPDATE squads SET status = 'active', deleted_at = NULL, updated_at = ? WHERE id = ? AND deleted_at IS NOT NULL",
|
|
2259
|
+
args: [now, id]
|
|
2260
|
+
});
|
|
2261
|
+
if (result.rowsAffected === 0) return null;
|
|
2262
|
+
return getSquadRow(id, database);
|
|
2263
|
+
}
|
|
2264
|
+
async function listDeletedSquads(db) {
|
|
2265
|
+
const database = db ?? await getDatabase();
|
|
2266
|
+
const result = await database.execute(
|
|
2267
|
+
"SELECT * FROM squads WHERE deleted_at IS NOT NULL ORDER BY deleted_at DESC, id DESC"
|
|
2268
|
+
);
|
|
2269
|
+
return result.rows.map((row) => mapSquad(row));
|
|
2270
|
+
}
|
|
2244
2271
|
async function getSquadByRepo(repoOwner, repoName, db) {
|
|
2245
2272
|
const database = db ?? await getDatabase();
|
|
2246
2273
|
const result = await database.execute({
|
|
2247
|
-
sql: "SELECT * FROM squads WHERE repo_owner = ? AND repo_name = ? LIMIT 1",
|
|
2274
|
+
sql: "SELECT * FROM squads WHERE repo_owner = ? AND repo_name = ? AND deleted_at IS NULL LIMIT 1",
|
|
2248
2275
|
args: [repoOwner, repoName]
|
|
2249
2276
|
});
|
|
2250
2277
|
const row = result.rows[0];
|
|
@@ -2348,7 +2375,8 @@ function mapSquad(row) {
|
|
|
2348
2375
|
status: asString(row.status),
|
|
2349
2376
|
config: parseJson(asString(row.config)),
|
|
2350
2377
|
createdAt: asString(row.created_at),
|
|
2351
|
-
updatedAt: asString(row.updated_at)
|
|
2378
|
+
updatedAt: asString(row.updated_at),
|
|
2379
|
+
deletedAt: asNullableString(row.deleted_at)
|
|
2352
2380
|
};
|
|
2353
2381
|
}
|
|
2354
2382
|
function mapMember(row) {
|
|
@@ -52850,6 +52878,39 @@ var init_squads2 = __esm({
|
|
|
52850
52878
|
});
|
|
52851
52879
|
}
|
|
52852
52880
|
});
|
|
52881
|
+
router7.get("/api/squads/deleted", async (_req, res) => {
|
|
52882
|
+
try {
|
|
52883
|
+
const squads = await listDeletedSquads();
|
|
52884
|
+
res.status(200).json({ squads });
|
|
52885
|
+
} catch (error51) {
|
|
52886
|
+
res.status(500).json({
|
|
52887
|
+
error: "Failed to list deleted squads",
|
|
52888
|
+
details: error51 instanceof Error ? error51.message : "Unknown error"
|
|
52889
|
+
});
|
|
52890
|
+
}
|
|
52891
|
+
});
|
|
52892
|
+
router7.post("/api/squads/:id/restore", async (req, res) => {
|
|
52893
|
+
try {
|
|
52894
|
+
const restored = await restoreSquad(req.params.id);
|
|
52895
|
+
if (!restored) {
|
|
52896
|
+
res.status(404).json({ error: "Squad not found or not deleted" });
|
|
52897
|
+
return;
|
|
52898
|
+
}
|
|
52899
|
+
await logActivity({
|
|
52900
|
+
squadId: restored.id,
|
|
52901
|
+
event: EVENT_NAMES.SQUAD_UPDATED,
|
|
52902
|
+
description: `Restored squad ${restored.name}`,
|
|
52903
|
+
metadata: { repoUrl: restored.repoUrl }
|
|
52904
|
+
});
|
|
52905
|
+
eventBus.emit(EVENT_NAMES.SQUAD_UPDATED, { squad: restored });
|
|
52906
|
+
res.status(200).json({ squad: restored });
|
|
52907
|
+
} catch (error51) {
|
|
52908
|
+
res.status(500).json({
|
|
52909
|
+
error: "Failed to restore squad",
|
|
52910
|
+
details: error51 instanceof Error ? error51.message : "Unknown error"
|
|
52911
|
+
});
|
|
52912
|
+
}
|
|
52913
|
+
});
|
|
52853
52914
|
router7.get("/api/squads/:id/members", async (req, res) => {
|
|
52854
52915
|
try {
|
|
52855
52916
|
const squad = await resolveSquad(req.params.id);
|
|
@@ -67985,6 +68046,10 @@ async function scrapeTokenUnitPricing() {
|
|
|
67985
68046
|
const html = await fetchPage(TOKEN_UNIT_COSTS_URL);
|
|
67986
68047
|
return parseTokenUnitTable(html);
|
|
67987
68048
|
}
|
|
68049
|
+
async function scrapeCopilotPricing() {
|
|
68050
|
+
const markdown = await fetchMarkdown(COPILOT_PRICING_URL);
|
|
68051
|
+
return parseCopilotPricingMarkdown(markdown);
|
|
68052
|
+
}
|
|
67988
68053
|
async function scrapePremiumRequestPricing() {
|
|
67989
68054
|
const html = await fetchPage(PREMIUM_MULTIPLIERS_URL);
|
|
67990
68055
|
return parsePremiumMultiplierTable(html);
|
|
@@ -68002,6 +68067,19 @@ async function fetchPage(url2) {
|
|
|
68002
68067
|
}
|
|
68003
68068
|
return response.text();
|
|
68004
68069
|
}
|
|
68070
|
+
async function fetchMarkdown(url2) {
|
|
68071
|
+
const response = await fetch(url2, {
|
|
68072
|
+
headers: {
|
|
68073
|
+
Accept: "text/markdown, text/plain, */*",
|
|
68074
|
+
"User-Agent": "IO-Daemon/4.0 (pricing-refresh)"
|
|
68075
|
+
},
|
|
68076
|
+
redirect: "follow"
|
|
68077
|
+
});
|
|
68078
|
+
if (!response.ok) {
|
|
68079
|
+
throw new Error(`Failed to fetch ${url2}: ${response.status} ${response.statusText}`);
|
|
68080
|
+
}
|
|
68081
|
+
return response.text();
|
|
68082
|
+
}
|
|
68005
68083
|
function parseTokenUnitTable(html) {
|
|
68006
68084
|
const results = [];
|
|
68007
68085
|
const tableRowPattern = /<tr[^>]*>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]*)<\/td>\s*<td[^>]*>([^<]+)<\/td>/gi;
|
|
@@ -68036,152 +68114,82 @@ function parsePremiumMultiplierTable(html) {
|
|
|
68036
68114
|
function cleanCellText(text) {
|
|
68037
68115
|
return text.replace(/<[^>]*>/g, "").replace(/&[^;]+;/g, " ").trim();
|
|
68038
68116
|
}
|
|
68039
|
-
|
|
68117
|
+
function parseCopilotPricingMarkdown(markdown) {
|
|
68118
|
+
const results = [];
|
|
68119
|
+
const seenModels = /* @__PURE__ */ new Set();
|
|
68120
|
+
const lines = markdown.split("\n");
|
|
68121
|
+
let columnIndices = null;
|
|
68122
|
+
for (const line of lines) {
|
|
68123
|
+
const trimmed = line.trim();
|
|
68124
|
+
if (!trimmed.startsWith("|")) continue;
|
|
68125
|
+
if (/\|\s*Model\s/i.test(trimmed)) {
|
|
68126
|
+
columnIndices = parseHeaderColumns(trimmed);
|
|
68127
|
+
continue;
|
|
68128
|
+
}
|
|
68129
|
+
if (/^[\s|:-]+$/.test(trimmed) || !columnIndices) continue;
|
|
68130
|
+
const entry = parseDataRow(trimmed, columnIndices);
|
|
68131
|
+
if (entry && !seenModels.has(entry.modelName.toLowerCase())) {
|
|
68132
|
+
seenModels.add(entry.modelName.toLowerCase());
|
|
68133
|
+
results.push(entry);
|
|
68134
|
+
}
|
|
68135
|
+
}
|
|
68136
|
+
return results;
|
|
68137
|
+
}
|
|
68138
|
+
function parseDataRow(line, columnIndices) {
|
|
68139
|
+
const cells = splitMarkdownRow(line);
|
|
68140
|
+
if (cells.length <= columnIndices.output) return null;
|
|
68141
|
+
const modelName = cells[columnIndices.model].trim();
|
|
68142
|
+
const inputPrice = parseDollarValue(cells[columnIndices.input]);
|
|
68143
|
+
const cachedPrice = columnIndices.cached >= 0 ? parseDollarValue(cells[columnIndices.cached]) : null;
|
|
68144
|
+
const outputPrice = parseDollarValue(cells[columnIndices.output]);
|
|
68145
|
+
if (!modelName || inputPrice === null || outputPrice === null) return null;
|
|
68146
|
+
return {
|
|
68147
|
+
modelName,
|
|
68148
|
+
inputMultiplier: inputPrice * PRICE_TO_MULTIPLIER,
|
|
68149
|
+
cachedInputMultiplier: cachedPrice !== null ? cachedPrice * PRICE_TO_MULTIPLIER : null,
|
|
68150
|
+
outputMultiplier: outputPrice * PRICE_TO_MULTIPLIER
|
|
68151
|
+
};
|
|
68152
|
+
}
|
|
68153
|
+
function parseHeaderColumns(headerLine) {
|
|
68154
|
+
const cells = splitMarkdownRow(headerLine).map((c) => c.trim().toLowerCase());
|
|
68155
|
+
const model = cells.findIndex((c) => c === "model" || c === "model name");
|
|
68156
|
+
const input2 = cells.findIndex(
|
|
68157
|
+
(c) => (c === "input" || c === "input multiplier") && !c.includes("cached")
|
|
68158
|
+
);
|
|
68159
|
+
const cached2 = cells.findIndex(
|
|
68160
|
+
(c) => c.includes("cached input") || c === "cached input multiplier"
|
|
68161
|
+
);
|
|
68162
|
+
const output2 = cells.findIndex(
|
|
68163
|
+
(c) => (c === "output" || c === "output multiplier") && !c.includes("cached")
|
|
68164
|
+
);
|
|
68165
|
+
if (model < 0 || input2 < 0 || output2 < 0) {
|
|
68166
|
+
return null;
|
|
68167
|
+
}
|
|
68168
|
+
return { model, input: input2, cached: cached2 >= 0 ? cached2 : -1, output: output2 };
|
|
68169
|
+
}
|
|
68170
|
+
function splitMarkdownRow(line) {
|
|
68171
|
+
const parts = line.split("|");
|
|
68172
|
+
if (parts[0].trim() === "") parts.shift();
|
|
68173
|
+
if (parts[parts.length - 1]?.trim() === "") parts.pop();
|
|
68174
|
+
return parts;
|
|
68175
|
+
}
|
|
68176
|
+
function parseDollarValue(cell) {
|
|
68177
|
+
if (!cell) return null;
|
|
68178
|
+
const cleaned = cell.trim().replace(/[$,]/g, "");
|
|
68179
|
+
if (cleaned.toLowerCase() === "n/a" || cleaned === "" || cleaned === "-") {
|
|
68180
|
+
return null;
|
|
68181
|
+
}
|
|
68182
|
+
const value = Number.parseFloat(cleaned);
|
|
68183
|
+
return Number.isNaN(value) ? null : value;
|
|
68184
|
+
}
|
|
68185
|
+
var TOKEN_UNIT_COSTS_URL, PREMIUM_MULTIPLIERS_URL, COPILOT_PRICING_URL, PRICE_TO_MULTIPLIER;
|
|
68040
68186
|
var init_pricing_scraper = __esm({
|
|
68041
68187
|
"packages/daemon/src/models/pricing-scraper.ts"() {
|
|
68042
68188
|
"use strict";
|
|
68043
68189
|
TOKEN_UNIT_COSTS_URL = "https://docs.github.com/en/billing/reference/costs-for-github-models";
|
|
68044
68190
|
PREMIUM_MULTIPLIERS_URL = "https://docs.github.com/en/copilot/reference/copilot-billing/request-based-billing-legacy/model-multipliers-for-annual-plans";
|
|
68045
|
-
|
|
68046
|
-
|
|
68047
|
-
|
|
68048
|
-
// packages/daemon/src/models/seed.ts
|
|
68049
|
-
var SEED_MODELS;
|
|
68050
|
-
var init_seed = __esm({
|
|
68051
|
-
"packages/daemon/src/models/seed.ts"() {
|
|
68052
|
-
"use strict";
|
|
68053
|
-
SEED_MODELS = [
|
|
68054
|
-
{
|
|
68055
|
-
id: "gpt-4o-mini",
|
|
68056
|
-
displayName: "OpenAI GPT-4o mini",
|
|
68057
|
-
premiumMultiplier: 0.33,
|
|
68058
|
-
tokenInputMultiplier: 0.015,
|
|
68059
|
-
tokenOutputMultiplier: 0.06,
|
|
68060
|
-
cachedInputMultiplier: 75e-4,
|
|
68061
|
-
tier: "trivial",
|
|
68062
|
-
available: true
|
|
68063
|
-
},
|
|
68064
|
-
{
|
|
68065
|
-
id: "gpt-4o",
|
|
68066
|
-
displayName: "OpenAI GPT-4o",
|
|
68067
|
-
premiumMultiplier: 0.33,
|
|
68068
|
-
tokenInputMultiplier: 0.25,
|
|
68069
|
-
tokenOutputMultiplier: 1,
|
|
68070
|
-
cachedInputMultiplier: 0.125,
|
|
68071
|
-
tier: "trivial",
|
|
68072
|
-
available: true
|
|
68073
|
-
},
|
|
68074
|
-
{
|
|
68075
|
-
id: "gpt-5-mini",
|
|
68076
|
-
displayName: "GPT-5 mini",
|
|
68077
|
-
premiumMultiplier: 0.33,
|
|
68078
|
-
tokenInputMultiplier: null,
|
|
68079
|
-
tokenOutputMultiplier: null,
|
|
68080
|
-
cachedInputMultiplier: null,
|
|
68081
|
-
tier: "trivial",
|
|
68082
|
-
available: true
|
|
68083
|
-
},
|
|
68084
|
-
{
|
|
68085
|
-
id: "claude-sonnet-4",
|
|
68086
|
-
displayName: "Claude Sonnet 4",
|
|
68087
|
-
premiumMultiplier: 6,
|
|
68088
|
-
tokenInputMultiplier: 0.6,
|
|
68089
|
-
tokenOutputMultiplier: 2.4,
|
|
68090
|
-
cachedInputMultiplier: null,
|
|
68091
|
-
tier: "premium",
|
|
68092
|
-
available: true
|
|
68093
|
-
},
|
|
68094
|
-
{
|
|
68095
|
-
id: "claude-haiku-4.5",
|
|
68096
|
-
displayName: "Claude Haiku 4.5",
|
|
68097
|
-
premiumMultiplier: 0.33,
|
|
68098
|
-
tokenInputMultiplier: null,
|
|
68099
|
-
tokenOutputMultiplier: null,
|
|
68100
|
-
cachedInputMultiplier: null,
|
|
68101
|
-
tier: "trivial",
|
|
68102
|
-
available: true
|
|
68103
|
-
},
|
|
68104
|
-
{
|
|
68105
|
-
id: "gemini-2.5-pro",
|
|
68106
|
-
displayName: "Gemini 2.5 Pro",
|
|
68107
|
-
premiumMultiplier: 1,
|
|
68108
|
-
tokenInputMultiplier: null,
|
|
68109
|
-
tokenOutputMultiplier: null,
|
|
68110
|
-
cachedInputMultiplier: null,
|
|
68111
|
-
tier: "fast",
|
|
68112
|
-
available: true
|
|
68113
|
-
},
|
|
68114
|
-
{
|
|
68115
|
-
id: "gpt-5.1",
|
|
68116
|
-
displayName: "GPT-5.1",
|
|
68117
|
-
premiumMultiplier: 3,
|
|
68118
|
-
tokenInputMultiplier: null,
|
|
68119
|
-
tokenOutputMultiplier: null,
|
|
68120
|
-
cachedInputMultiplier: null,
|
|
68121
|
-
tier: "standard",
|
|
68122
|
-
available: true
|
|
68123
|
-
},
|
|
68124
|
-
{
|
|
68125
|
-
id: "gpt-5.2",
|
|
68126
|
-
displayName: "GPT-5.2",
|
|
68127
|
-
premiumMultiplier: 3,
|
|
68128
|
-
tokenInputMultiplier: null,
|
|
68129
|
-
tokenOutputMultiplier: null,
|
|
68130
|
-
cachedInputMultiplier: null,
|
|
68131
|
-
tier: "standard",
|
|
68132
|
-
available: true
|
|
68133
|
-
},
|
|
68134
|
-
{
|
|
68135
|
-
id: "gpt-5.4",
|
|
68136
|
-
displayName: "GPT-5.4",
|
|
68137
|
-
premiumMultiplier: 6,
|
|
68138
|
-
tokenInputMultiplier: null,
|
|
68139
|
-
tokenOutputMultiplier: null,
|
|
68140
|
-
cachedInputMultiplier: null,
|
|
68141
|
-
tier: "premium",
|
|
68142
|
-
available: true
|
|
68143
|
-
},
|
|
68144
|
-
{
|
|
68145
|
-
id: "claude-opus-4.5",
|
|
68146
|
-
displayName: "Claude Opus 4.5",
|
|
68147
|
-
premiumMultiplier: 15,
|
|
68148
|
-
tokenInputMultiplier: null,
|
|
68149
|
-
tokenOutputMultiplier: null,
|
|
68150
|
-
cachedInputMultiplier: null,
|
|
68151
|
-
tier: "premium",
|
|
68152
|
-
available: true
|
|
68153
|
-
},
|
|
68154
|
-
{
|
|
68155
|
-
id: "claude-opus-4.6",
|
|
68156
|
-
displayName: "Claude Opus 4.6",
|
|
68157
|
-
premiumMultiplier: 27,
|
|
68158
|
-
tokenInputMultiplier: null,
|
|
68159
|
-
tokenOutputMultiplier: null,
|
|
68160
|
-
cachedInputMultiplier: null,
|
|
68161
|
-
tier: "ultra",
|
|
68162
|
-
available: true
|
|
68163
|
-
},
|
|
68164
|
-
{
|
|
68165
|
-
id: "claude-opus-4.7",
|
|
68166
|
-
displayName: "Claude Opus 4.7",
|
|
68167
|
-
premiumMultiplier: 27,
|
|
68168
|
-
tokenInputMultiplier: null,
|
|
68169
|
-
tokenOutputMultiplier: null,
|
|
68170
|
-
cachedInputMultiplier: null,
|
|
68171
|
-
tier: "ultra",
|
|
68172
|
-
available: true
|
|
68173
|
-
},
|
|
68174
|
-
{
|
|
68175
|
-
id: "gpt-5.5",
|
|
68176
|
-
displayName: "GPT-5.5",
|
|
68177
|
-
premiumMultiplier: 57,
|
|
68178
|
-
tokenInputMultiplier: null,
|
|
68179
|
-
tokenOutputMultiplier: null,
|
|
68180
|
-
cachedInputMultiplier: null,
|
|
68181
|
-
tier: "ultra",
|
|
68182
|
-
available: true
|
|
68183
|
-
}
|
|
68184
|
-
];
|
|
68191
|
+
COPILOT_PRICING_URL = "https://docs.github.com/api/article/body?pathname=/en/copilot/reference/copilot-billing/models-and-pricing";
|
|
68192
|
+
PRICE_TO_MULTIPLIER = 0.1;
|
|
68185
68193
|
}
|
|
68186
68194
|
});
|
|
68187
68195
|
|
|
@@ -68282,22 +68290,52 @@ async function scrapePremiumPricingIntoMap(modelMap, result, logger2) {
|
|
|
68282
68290
|
logger2?.warn(`Premium pricing scrape failed: ${msg}`);
|
|
68283
68291
|
}
|
|
68284
68292
|
}
|
|
68293
|
+
async function scrapeCopilotPricingIntoMap(modelMap, result, logger2) {
|
|
68294
|
+
try {
|
|
68295
|
+
const copilotPricing = await scrapeCopilotPricing();
|
|
68296
|
+
result.copilotPricingScraped = true;
|
|
68297
|
+
for (const cp of copilotPricing) {
|
|
68298
|
+
const key = normalizeModelName(cp.modelName);
|
|
68299
|
+
const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
|
|
68300
|
+
if (existing) {
|
|
68301
|
+
existing.tokenInputMultiplier = cp.inputMultiplier;
|
|
68302
|
+
existing.tokenOutputMultiplier = cp.outputMultiplier;
|
|
68303
|
+
if (cp.cachedInputMultiplier !== null) {
|
|
68304
|
+
existing.cachedInputMultiplier = cp.cachedInputMultiplier;
|
|
68305
|
+
}
|
|
68306
|
+
} else {
|
|
68307
|
+
modelMap.set(key, {
|
|
68308
|
+
id: key,
|
|
68309
|
+
displayName: cp.modelName,
|
|
68310
|
+
tokenInputMultiplier: cp.inputMultiplier,
|
|
68311
|
+
tokenOutputMultiplier: cp.outputMultiplier,
|
|
68312
|
+
cachedInputMultiplier: cp.cachedInputMultiplier,
|
|
68313
|
+
available: true
|
|
68314
|
+
});
|
|
68315
|
+
}
|
|
68316
|
+
}
|
|
68317
|
+
} catch (error51) {
|
|
68318
|
+
const msg = error51 instanceof Error ? error51.message : String(error51);
|
|
68319
|
+
result.errors.push(`Copilot pricing scrape failed: ${msg}`);
|
|
68320
|
+
logger2?.warn(`Copilot pricing scrape failed: ${msg}`);
|
|
68321
|
+
}
|
|
68322
|
+
}
|
|
68285
68323
|
async function refreshModelPricing(logger2) {
|
|
68286
68324
|
const result = {
|
|
68287
68325
|
modelsUpdated: 0,
|
|
68288
68326
|
catalogFetched: false,
|
|
68289
68327
|
tokenPricingScraped: false,
|
|
68290
68328
|
premiumPricingScraped: false,
|
|
68329
|
+
copilotPricingScraped: false,
|
|
68291
68330
|
errors: []
|
|
68292
68331
|
};
|
|
68293
68332
|
const modelMap = /* @__PURE__ */ new Map();
|
|
68294
68333
|
await fetchCatalogIntoMap(modelMap, result, logger2);
|
|
68295
68334
|
await scrapeTokenPricingIntoMap(modelMap, result, logger2);
|
|
68335
|
+
await scrapeCopilotPricingIntoMap(modelMap, result, logger2);
|
|
68296
68336
|
await scrapePremiumPricingIntoMap(modelMap, result, logger2);
|
|
68297
|
-
if (!result.catalogFetched && !result.tokenPricingScraped && !result.premiumPricingScraped) {
|
|
68298
|
-
logger2?.warn("All pricing sources failed,
|
|
68299
|
-
await seedFromFallback();
|
|
68300
|
-
result.modelsUpdated = SEED_MODELS.length;
|
|
68337
|
+
if (!result.catalogFetched && !result.tokenPricingScraped && !result.premiumPricingScraped && !result.copilotPricingScraped) {
|
|
68338
|
+
logger2?.warn("All pricing sources failed, no models available");
|
|
68301
68339
|
return result;
|
|
68302
68340
|
}
|
|
68303
68341
|
const db = await getDatabase();
|
|
@@ -68319,13 +68357,6 @@ async function refreshModelPricing(logger2) {
|
|
|
68319
68357
|
}
|
|
68320
68358
|
return result;
|
|
68321
68359
|
}
|
|
68322
|
-
async function seedFromFallback() {
|
|
68323
|
-
const db = await getDatabase();
|
|
68324
|
-
const now = nowIso();
|
|
68325
|
-
for (const model of SEED_MODELS) {
|
|
68326
|
-
await upsertModel(db, { ...model, updatedAt: now });
|
|
68327
|
-
}
|
|
68328
|
-
}
|
|
68329
68360
|
async function getModelPricing(modelId) {
|
|
68330
68361
|
const db = await getDatabase();
|
|
68331
68362
|
const result = await db.execute({
|
|
@@ -68406,7 +68437,6 @@ var init_registry = __esm({
|
|
|
68406
68437
|
init_db();
|
|
68407
68438
|
init_catalog();
|
|
68408
68439
|
init_pricing_scraper();
|
|
68409
|
-
init_seed();
|
|
68410
68440
|
init_types();
|
|
68411
68441
|
}
|
|
68412
68442
|
});
|
|
@@ -68417,7 +68447,6 @@ var init_models = __esm({
|
|
|
68417
68447
|
"use strict";
|
|
68418
68448
|
init_catalog();
|
|
68419
68449
|
init_registry();
|
|
68420
|
-
init_seed();
|
|
68421
68450
|
init_types();
|
|
68422
68451
|
}
|
|
68423
68452
|
});
|
|
@@ -70857,7 +70886,7 @@ async function processQueue2(squadId) {
|
|
|
70857
70886
|
const next = await getNextQueued(squadId);
|
|
70858
70887
|
if (next) {
|
|
70859
70888
|
const freshSquad = await getSquad(squadId);
|
|
70860
|
-
if (freshSquad) {
|
|
70889
|
+
if (freshSquad && next.objectiveId) {
|
|
70861
70890
|
void startAndExecuteInstance(next.id, freshSquad, next.objectiveId);
|
|
70862
70891
|
}
|
|
70863
70892
|
}
|
|
@@ -70992,13 +71021,28 @@ async function handleFireSquad(rawArgs) {
|
|
|
70992
71021
|
if (activeObjectives.length > 0) {
|
|
70993
71022
|
const updated = await updateSquad(squadId, { status: "inactive" });
|
|
70994
71023
|
return {
|
|
70995
|
-
message: `Squad ${squadId} was deactivated because it still has active objectives.`,
|
|
71024
|
+
message: `Squad ${squadId} was deactivated because it still has active objectives. Use fire_squad again after objectives complete to delete it.`,
|
|
70996
71025
|
squad: updated,
|
|
70997
71026
|
activeObjectives
|
|
70998
71027
|
};
|
|
70999
71028
|
}
|
|
71000
71029
|
await deleteSquad(squadId);
|
|
71001
|
-
return {
|
|
71030
|
+
return {
|
|
71031
|
+
message: `Squad "${squad.name}" has been deleted. It can be restored with restore_squad if needed.`,
|
|
71032
|
+
squadId
|
|
71033
|
+
};
|
|
71034
|
+
}
|
|
71035
|
+
async function handleRestoreSquad(rawArgs) {
|
|
71036
|
+
const { squadId } = squadIdSchema.parse(rawArgs);
|
|
71037
|
+
const restored = await restoreSquad(squadId);
|
|
71038
|
+
if (!restored) {
|
|
71039
|
+
throw new Error(`Squad ${squadId} was not found or is not deleted.`);
|
|
71040
|
+
}
|
|
71041
|
+
eventBus.emit(EVENT_NAMES.SQUAD_UPDATED, { squad: restored });
|
|
71042
|
+
return {
|
|
71043
|
+
message: `Squad "${restored.name}" has been restored.`,
|
|
71044
|
+
squad: restored
|
|
71045
|
+
};
|
|
71002
71046
|
}
|
|
71003
71047
|
async function handleDelegateToSquad(rawArgs) {
|
|
71004
71048
|
const { squadId, objective } = delegateToSquadSchema.parse(rawArgs);
|
|
@@ -71048,7 +71092,7 @@ async function handleUpdateSquadMember(rawArgs) {
|
|
|
71048
71092
|
member: updated
|
|
71049
71093
|
};
|
|
71050
71094
|
}
|
|
71051
|
-
function createSquadToolExecutor(
|
|
71095
|
+
function createSquadToolExecutor(_config) {
|
|
71052
71096
|
return async (toolName, rawArgs) => {
|
|
71053
71097
|
switch (toolName) {
|
|
71054
71098
|
case "create_squad":
|
|
@@ -71063,11 +71107,26 @@ function createSquadToolExecutor(config2) {
|
|
|
71063
71107
|
return handleAnalyzeRepo(rawArgs);
|
|
71064
71108
|
case "fire_squad":
|
|
71065
71109
|
return handleFireSquad(rawArgs);
|
|
71110
|
+
case "restore_squad":
|
|
71111
|
+
return handleRestoreSquad(rawArgs);
|
|
71112
|
+
case "list_deleted_squads": {
|
|
71113
|
+
const deletedSquads = await listDeletedSquads();
|
|
71114
|
+
if (deletedSquads.length === 0) {
|
|
71115
|
+
return { message: "No deleted squads.", squads: [] };
|
|
71116
|
+
}
|
|
71117
|
+
const list = deletedSquads.map((s) => `${s.id}: ${s.name} (${s.repoOwner}/${s.repoName}) [deleted ${s.deletedAt}]`).join("\n");
|
|
71118
|
+
return { message: list, squads: deletedSquads };
|
|
71119
|
+
}
|
|
71066
71120
|
case "list_squads": {
|
|
71067
71121
|
const squads = await listSquads();
|
|
71122
|
+
const deletedCount = (await listDeletedSquads()).length;
|
|
71123
|
+
const suffix = deletedCount > 0 ? `
|
|
71124
|
+
|
|
71125
|
+
${deletedCount} deleted squad(s) available for restore (use list_deleted_squads to view).` : "";
|
|
71068
71126
|
return {
|
|
71069
|
-
message: formatSquadList(squads),
|
|
71070
|
-
squads
|
|
71127
|
+
message: formatSquadList(squads) + suffix,
|
|
71128
|
+
squads,
|
|
71129
|
+
deletedCount
|
|
71071
71130
|
};
|
|
71072
71131
|
}
|
|
71073
71132
|
case "get_squad_status": {
|
|
@@ -71125,7 +71184,9 @@ var init_squad2 = __esm({
|
|
|
71125
71184
|
squadId: external_exports.string().trim().min(1),
|
|
71126
71185
|
role: external_exports.string().trim().min(1).describe("Slug-style role identifier (e.g. 'senior-frontend-engineer', 'team-lead')"),
|
|
71127
71186
|
name: external_exports.string().trim().min(1).describe("Display name for the member (e.g. 'Senior Frontend Engineer')"),
|
|
71128
|
-
systemPrompt: external_exports.string().min(1).describe(
|
|
71187
|
+
systemPrompt: external_exports.string().min(1).describe(
|
|
71188
|
+
"The system prompt defining this member's expertise, responsibilities, and behavior."
|
|
71189
|
+
),
|
|
71129
71190
|
model: external_exports.string().optional().describe("Model override for this member. Uses squad default if not provided.")
|
|
71130
71191
|
});
|
|
71131
71192
|
removeSquadMemberSchema = external_exports.object({
|
|
@@ -71197,10 +71258,22 @@ var init_squad2 = __esm({
|
|
|
71197
71258
|
},
|
|
71198
71259
|
{
|
|
71199
71260
|
name: "fire_squad",
|
|
71200
|
-
description: "
|
|
71261
|
+
description: "Soft-delete a squad. The squad can be restored later with restore_squad.",
|
|
71201
71262
|
parameters: squadIdSchema,
|
|
71202
71263
|
skipPermission: true
|
|
71203
71264
|
},
|
|
71265
|
+
{
|
|
71266
|
+
name: "restore_squad",
|
|
71267
|
+
description: "Restore a previously deleted squad and all its members.",
|
|
71268
|
+
parameters: squadIdSchema,
|
|
71269
|
+
skipPermission: true
|
|
71270
|
+
},
|
|
71271
|
+
{
|
|
71272
|
+
name: "list_deleted_squads",
|
|
71273
|
+
description: "List all soft-deleted squads that can be restored.",
|
|
71274
|
+
parameters: external_exports.object({}),
|
|
71275
|
+
skipPermission: true
|
|
71276
|
+
},
|
|
71204
71277
|
{
|
|
71205
71278
|
name: "list_squads",
|
|
71206
71279
|
description: "List all squads and their status.",
|
|
@@ -85313,8 +85386,7 @@ async function main() {
|
|
|
85313
85386
|
logger2.info("Database initialized");
|
|
85314
85387
|
const pricingResult = await refreshModelPricing(logger2);
|
|
85315
85388
|
if (pricingResult.modelsUpdated === 0) {
|
|
85316
|
-
logger2.warn("Model pricing refresh returned 0 models
|
|
85317
|
-
await seedFromFallback();
|
|
85389
|
+
logger2.warn("Model pricing refresh returned 0 models");
|
|
85318
85390
|
}
|
|
85319
85391
|
logger2.info({ modelsUpdated: pricingResult.modelsUpdated }, "Model pricing initialized");
|
|
85320
85392
|
await scanSkills();
|