heyio 4.3.2 → 4.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -79,7 +79,7 @@ var init_constants = __esm({
79
79
  "packages/shared/dist/constants.js"() {
80
80
  "use strict";
81
81
  APP_NAME = "io";
82
- APP_VERSION = "4.3.2";
82
+ APP_VERSION = "4.3.4";
83
83
  API_PORT = 7777;
84
84
  API_HOST = "0.0.0.0";
85
85
  DEFAULT_MODEL = "gpt-4.1-mini";
@@ -152,349 +152,6 @@ var init_paths = __esm({
152
152
  }
153
153
  });
154
154
 
155
- // packages/daemon/src/store/db.ts
156
- import { mkdir } from "node:fs/promises";
157
- import { dirname } from "node:path";
158
- import { pathToFileURL } from "node:url";
159
- import { createClient } from "@libsql/client";
160
- function asString(value) {
161
- if (typeof value === "string") {
162
- return value;
163
- }
164
- if (value === null || value === void 0) {
165
- throw new Error("Expected string value but received null or undefined");
166
- }
167
- return String(value);
168
- }
169
- function asNullableString(value) {
170
- if (value === null || value === void 0) {
171
- return null;
172
- }
173
- return typeof value === "string" ? value : String(value);
174
- }
175
- function asNumber(value) {
176
- if (typeof value === "number") {
177
- return value;
178
- }
179
- if (typeof value === "bigint") {
180
- return Number(value);
181
- }
182
- if (typeof value === "string") {
183
- return Number(value);
184
- }
185
- throw new Error(`Expected numeric value but received ${typeof value}`);
186
- }
187
- function asNullableNumber(value) {
188
- if (value === null || value === void 0) {
189
- return null;
190
- }
191
- return asNumber(value);
192
- }
193
- function asBoolean(value) {
194
- return asNumber(value) === 1;
195
- }
196
- function toSqliteBoolean(value) {
197
- return value ? 1 : 0;
198
- }
199
- function parseJson(value) {
200
- if (typeof value !== "string") {
201
- return value;
202
- }
203
- return JSON.parse(value);
204
- }
205
- function serializeJson(value) {
206
- return JSON.stringify(value);
207
- }
208
- async function initDatabase() {
209
- if (client && !client.closed) {
210
- return client;
211
- }
212
- if (initPromise) {
213
- return initPromise;
214
- }
215
- initPromise = initializeDatabase(defaultConnectionOptions);
216
- try {
217
- client = await initPromise;
218
- return client;
219
- } finally {
220
- initPromise = null;
221
- }
222
- }
223
- async function getDatabase() {
224
- return initDatabase();
225
- }
226
- async function initializeDatabase(options2 = {}) {
227
- const url2 = await resolveDatabaseUrl(options2);
228
- const databaseClient = createClient({ url: url2 });
229
- await databaseClient.execute("PRAGMA foreign_keys = ON");
230
- await databaseClient.execute("PRAGMA journal_mode = WAL");
231
- await ensureMigrationTable(databaseClient);
232
- await applyMigrations(databaseClient);
233
- return databaseClient;
234
- }
235
- async function resolveDatabaseUrl(options2) {
236
- if (options2.url) {
237
- return options2.url;
238
- }
239
- const databasePath = options2.path ?? DB_PATH;
240
- await mkdir(dirname(databasePath), { recursive: true });
241
- return pathToFileURL(databasePath).href;
242
- }
243
- async function ensureMigrationTable(databaseClient) {
244
- await databaseClient.executeMultiple(`
245
- CREATE TABLE IF NOT EXISTS schema_migrations (
246
- version INTEGER PRIMARY KEY,
247
- name TEXT NOT NULL,
248
- applied_at TEXT NOT NULL
249
- );
250
- `);
251
- }
252
- async function applyMigrations(databaseClient) {
253
- const appliedVersions = await getAppliedVersions(databaseClient);
254
- for (const migration of MIGRATIONS) {
255
- if (appliedVersions.has(migration.version)) {
256
- continue;
257
- }
258
- const transaction = await databaseClient.transaction("write");
259
- try {
260
- for (const statement of migration.statements) {
261
- await transaction.execute(statement);
262
- }
263
- await transaction.execute({
264
- sql: "INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",
265
- args: [migration.version, migration.name, nowIso()]
266
- });
267
- await transaction.commit();
268
- } catch (error51) {
269
- if (!transaction.closed) {
270
- await transaction.rollback();
271
- }
272
- throw error51;
273
- } finally {
274
- if (!transaction.closed) {
275
- transaction.close();
276
- }
277
- }
278
- }
279
- }
280
- async function getAppliedVersions(databaseClient) {
281
- const result = await databaseClient.execute(
282
- "SELECT version FROM schema_migrations ORDER BY version ASC"
283
- );
284
- return new Set(result.rows.map((row) => asNumber(row.version)));
285
- }
286
- var MIGRATIONS, client, initPromise, defaultConnectionOptions, generateId, nowIso;
287
- var init_db = __esm({
288
- "packages/daemon/src/store/db.ts"() {
289
- "use strict";
290
- init_paths();
291
- MIGRATIONS = [
292
- {
293
- version: 1,
294
- name: "create-store-schema",
295
- statements: [
296
- `CREATE TABLE IF NOT EXISTS squads (
297
- id TEXT PRIMARY KEY,
298
- name TEXT NOT NULL,
299
- repo_url TEXT NOT NULL,
300
- repo_owner TEXT NOT NULL,
301
- repo_name TEXT NOT NULL,
302
- status TEXT NOT NULL,
303
- config TEXT NOT NULL,
304
- created_at TEXT NOT NULL,
305
- updated_at TEXT NOT NULL,
306
- UNIQUE (repo_owner, repo_name)
307
- )`,
308
- `CREATE TABLE IF NOT EXISTS squad_members (
309
- id TEXT PRIMARY KEY,
310
- squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
311
- role TEXT NOT NULL,
312
- name TEXT NOT NULL,
313
- system_prompt TEXT NOT NULL,
314
- model TEXT,
315
- created_at TEXT NOT NULL
316
- )`,
317
- `CREATE TABLE IF NOT EXISTS objectives (
318
- id TEXT PRIMARY KEY,
319
- squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
320
- description TEXT NOT NULL,
321
- status TEXT NOT NULL,
322
- plan TEXT,
323
- revision_count INTEGER NOT NULL DEFAULT 0,
324
- branch TEXT,
325
- pr_url TEXT,
326
- created_at TEXT NOT NULL,
327
- updated_at TEXT NOT NULL
328
- )`,
329
- `CREATE TABLE IF NOT EXISTS tasks (
330
- id TEXT PRIMARY KEY,
331
- objective_id TEXT NOT NULL REFERENCES objectives(id) ON DELETE CASCADE,
332
- assignee_id TEXT REFERENCES squad_members(id) ON DELETE SET NULL,
333
- title TEXT NOT NULL,
334
- description TEXT NOT NULL,
335
- status TEXT NOT NULL,
336
- result TEXT,
337
- created_at TEXT NOT NULL,
338
- updated_at TEXT NOT NULL
339
- )`,
340
- `CREATE TABLE IF NOT EXISTS conversations (
341
- id TEXT PRIMARY KEY,
342
- title TEXT,
343
- source TEXT NOT NULL,
344
- created_at TEXT NOT NULL,
345
- updated_at TEXT NOT NULL
346
- )`,
347
- `CREATE TABLE IF NOT EXISTS messages (
348
- id TEXT PRIMARY KEY,
349
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
350
- role TEXT NOT NULL,
351
- content TEXT NOT NULL,
352
- model TEXT,
353
- input_tokens INTEGER,
354
- output_tokens INTEGER,
355
- created_at TEXT NOT NULL
356
- )`,
357
- `CREATE TABLE IF NOT EXISTS inbox (
358
- id TEXT PRIMARY KEY,
359
- squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
360
- objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
361
- type TEXT NOT NULL,
362
- title TEXT NOT NULL,
363
- content TEXT NOT NULL,
364
- status TEXT NOT NULL,
365
- reply TEXT,
366
- created_at TEXT NOT NULL,
367
- updated_at TEXT NOT NULL
368
- )`,
369
- `CREATE TABLE IF NOT EXISTS schedules (
370
- id TEXT PRIMARY KEY,
371
- name TEXT NOT NULL,
372
- cron_expression TEXT NOT NULL,
373
- prompt TEXT NOT NULL,
374
- enabled INTEGER NOT NULL DEFAULT 1,
375
- last_run_at TEXT,
376
- next_run_at TEXT,
377
- created_at TEXT NOT NULL,
378
- updated_at TEXT NOT NULL
379
- )`,
380
- `CREATE TABLE IF NOT EXISTS token_usage (
381
- id TEXT PRIMARY KEY,
382
- squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
383
- agent_id TEXT,
384
- model TEXT NOT NULL,
385
- input_tokens INTEGER NOT NULL,
386
- output_tokens INTEGER NOT NULL,
387
- cost REAL NOT NULL,
388
- created_at TEXT NOT NULL
389
- )`,
390
- `CREATE TABLE IF NOT EXISTS activity (
391
- id TEXT PRIMARY KEY,
392
- squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
393
- objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
394
- event TEXT NOT NULL,
395
- description TEXT NOT NULL,
396
- metadata TEXT,
397
- created_at TEXT NOT NULL
398
- )`,
399
- `CREATE TABLE IF NOT EXISTS agent_history (
400
- id TEXT PRIMARY KEY,
401
- agent_id TEXT NOT NULL,
402
- squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
403
- content TEXT NOT NULL,
404
- created_at TEXT NOT NULL
405
- )`,
406
- `CREATE TABLE IF NOT EXISTS settings (
407
- key TEXT PRIMARY KEY,
408
- value TEXT
409
- )`,
410
- "CREATE INDEX IF NOT EXISTS idx_squad_members_squad_id ON squad_members(squad_id)",
411
- "CREATE INDEX IF NOT EXISTS idx_objectives_squad_id ON objectives(squad_id)",
412
- "CREATE INDEX IF NOT EXISTS idx_objectives_status ON objectives(status)",
413
- "CREATE INDEX IF NOT EXISTS idx_tasks_objective_id ON tasks(objective_id)",
414
- "CREATE INDEX IF NOT EXISTS idx_tasks_assignee_id ON tasks(assignee_id)",
415
- "CREATE INDEX IF NOT EXISTS idx_messages_conversation_id_created_at ON messages(conversation_id, created_at)",
416
- "CREATE INDEX IF NOT EXISTS idx_inbox_status_created_at ON inbox(status, created_at)",
417
- "CREATE INDEX IF NOT EXISTS idx_inbox_squad_id ON inbox(squad_id)",
418
- "CREATE INDEX IF NOT EXISTS idx_inbox_objective_id ON inbox(objective_id)",
419
- "CREATE INDEX IF NOT EXISTS idx_schedules_enabled_next_run_at ON schedules(enabled, next_run_at)",
420
- "CREATE INDEX IF NOT EXISTS idx_token_usage_created_at ON token_usage(created_at)",
421
- "CREATE INDEX IF NOT EXISTS idx_token_usage_squad_id ON token_usage(squad_id)",
422
- "CREATE INDEX IF NOT EXISTS idx_token_usage_agent_id ON token_usage(agent_id)",
423
- "CREATE INDEX IF NOT EXISTS idx_token_usage_model ON token_usage(model)",
424
- "CREATE INDEX IF NOT EXISTS idx_activity_created_at ON activity(created_at)",
425
- "CREATE INDEX IF NOT EXISTS idx_activity_squad_id ON activity(squad_id)",
426
- "CREATE INDEX IF NOT EXISTS idx_activity_objective_id ON activity(objective_id)",
427
- "CREATE INDEX IF NOT EXISTS idx_agent_history_agent_id_created_at ON agent_history(agent_id, created_at)"
428
- ]
429
- },
430
- {
431
- version: 2,
432
- name: "add-model-pricing-and-dual-costs",
433
- statements: [
434
- `CREATE TABLE IF NOT EXISTS model_pricing (
435
- id TEXT PRIMARY KEY,
436
- display_name TEXT NOT NULL,
437
- premium_multiplier REAL,
438
- token_input_multiplier REAL,
439
- token_output_multiplier REAL,
440
- cached_input_multiplier REAL,
441
- tier TEXT NOT NULL,
442
- available INTEGER NOT NULL DEFAULT 1,
443
- updated_at TEXT NOT NULL
444
- )`,
445
- "CREATE INDEX IF NOT EXISTS idx_model_pricing_tier ON model_pricing(tier)",
446
- "CREATE INDEX IF NOT EXISTS idx_model_pricing_available ON model_pricing(available)",
447
- "ALTER TABLE token_usage ADD COLUMN premium_request_cost REAL",
448
- "ALTER TABLE token_usage ADD COLUMN token_unit_cost REAL"
449
- ]
450
- },
451
- {
452
- version: 3,
453
- name: "add-squad-instances",
454
- statements: [
455
- `CREATE TABLE IF NOT EXISTS squad_instances (
456
- id TEXT PRIMARY KEY,
457
- squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
458
- objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
459
- status TEXT NOT NULL DEFAULT 'queued',
460
- branch TEXT,
461
- worktree_path TEXT,
462
- created_at TEXT NOT NULL,
463
- started_at TEXT,
464
- completed_at TEXT,
465
- error TEXT
466
- )`,
467
- "CREATE INDEX IF NOT EXISTS idx_squad_instances_squad_status ON squad_instances(squad_id, status)",
468
- "CREATE INDEX IF NOT EXISTS idx_squad_instances_status ON squad_instances(status)",
469
- "CREATE INDEX IF NOT EXISTS idx_squad_instances_objective_id ON squad_instances(objective_id)"
470
- ]
471
- },
472
- {
473
- version: 4,
474
- name: "denormalize-usage-names",
475
- statements: [
476
- "ALTER TABLE token_usage ADD COLUMN squad_name TEXT",
477
- "ALTER TABLE token_usage ADD COLUMN agent_name TEXT",
478
- `UPDATE token_usage SET
479
- squad_name = (SELECT s.name FROM squads s WHERE s.id = token_usage.squad_id),
480
- agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
481
- WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
482
- ]
483
- },
484
- {
485
- version: 5,
486
- name: "add-squad-soft-delete",
487
- statements: ["ALTER TABLE squads ADD COLUMN deleted_at TEXT"]
488
- }
489
- ];
490
- client = null;
491
- initPromise = null;
492
- defaultConnectionOptions = {};
493
- generateId = () => crypto.randomUUID();
494
- nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
495
- }
496
- });
497
-
498
155
  // node_modules/cron-parser/dist/fields/types.js
499
156
  var require_types = __commonJS({
500
157
  "node_modules/cron-parser/dist/fields/types.js"(exports2) {
@@ -62549,498 +62206,6 @@ var require_websocket_server = __commonJS({
62549
62206
  }
62550
62207
  });
62551
62208
 
62552
- // packages/daemon/src/models/catalog.ts
62553
- import { execFileSync } from "node:child_process";
62554
- function resolveGitHubToken() {
62555
- const envToken = process.env.GITHUB_TOKEN?.trim();
62556
- if (envToken && envToken.length > 0) {
62557
- return envToken;
62558
- }
62559
- try {
62560
- const token = execFileSync("gh", ["auth", "token"], {
62561
- encoding: "utf8",
62562
- stdio: ["ignore", "pipe", "pipe"]
62563
- }).trim();
62564
- return token.length > 0 ? token : void 0;
62565
- } catch {
62566
- return void 0;
62567
- }
62568
- }
62569
- async function fetchModelCatalog() {
62570
- const token = resolveGitHubToken();
62571
- if (!token) {
62572
- throw new Error("No GitHub token available for model catalog fetch");
62573
- }
62574
- const response = await fetch(CATALOG_URL, {
62575
- headers: {
62576
- Accept: "application/json",
62577
- Authorization: `Bearer ${token}`,
62578
- "X-GitHub-Api-Version": "2024-12-01"
62579
- }
62580
- });
62581
- if (!response.ok) {
62582
- throw new Error(`Model catalog fetch failed: ${response.status} ${response.statusText}`);
62583
- }
62584
- const data = await response.json();
62585
- if (!Array.isArray(data)) {
62586
- throw new Error("Model catalog response is not an array");
62587
- }
62588
- const models = [];
62589
- for (const entry of data) {
62590
- const id = entry.id ?? entry.name;
62591
- const displayName = entry.friendly_name ?? entry.name ?? id;
62592
- if (id && typeof id === "string") {
62593
- models.push({ id, displayName: displayName ?? id });
62594
- }
62595
- }
62596
- return models;
62597
- }
62598
- var CATALOG_URL;
62599
- var init_catalog = __esm({
62600
- "packages/daemon/src/models/catalog.ts"() {
62601
- "use strict";
62602
- CATALOG_URL = "https://models.github.ai/catalog/models";
62603
- }
62604
- });
62605
-
62606
- // packages/daemon/src/models/pricing-scraper.ts
62607
- async function scrapeTokenUnitPricing() {
62608
- const html = await fetchPage(TOKEN_UNIT_COSTS_URL);
62609
- return parseTokenUnitTable(html);
62610
- }
62611
- async function scrapeCopilotPricing() {
62612
- const markdown = await fetchMarkdown(COPILOT_PRICING_URL);
62613
- return parseCopilotPricingMarkdown(markdown);
62614
- }
62615
- async function scrapePremiumRequestPricing() {
62616
- const html = await fetchPage(PREMIUM_MULTIPLIERS_URL);
62617
- return parsePremiumMultiplierTable(html);
62618
- }
62619
- async function fetchPage(url2) {
62620
- const response = await fetch(url2, {
62621
- headers: {
62622
- Accept: "text/html",
62623
- "User-Agent": "IO-Daemon/4.0 (pricing-refresh)"
62624
- },
62625
- redirect: "follow"
62626
- });
62627
- if (!response.ok) {
62628
- throw new Error(`Failed to fetch ${url2}: ${response.status} ${response.statusText}`);
62629
- }
62630
- return response.text();
62631
- }
62632
- async function fetchMarkdown(url2) {
62633
- const response = await fetch(url2, {
62634
- headers: {
62635
- Accept: "text/markdown, text/plain, */*",
62636
- "User-Agent": "IO-Daemon/4.0 (pricing-refresh)"
62637
- },
62638
- redirect: "follow"
62639
- });
62640
- if (!response.ok) {
62641
- throw new Error(`Failed to fetch ${url2}: ${response.status} ${response.statusText}`);
62642
- }
62643
- return response.text();
62644
- }
62645
- function parseTokenUnitTable(html) {
62646
- const results = [];
62647
- const tableRowPattern = /<tr[^>]*>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]*)<\/td>\s*<td[^>]*>([^<]+)<\/td>/gi;
62648
- for (const match of html.matchAll(tableRowPattern)) {
62649
- const modelName = cleanCellText(match[1]);
62650
- const inputMultiplier = Number.parseFloat(match[2]);
62651
- const cachedInput = match[3].trim().toLowerCase();
62652
- const outputMultiplier = Number.parseFloat(match[4]);
62653
- if (modelName && !Number.isNaN(inputMultiplier) && !Number.isNaN(outputMultiplier)) {
62654
- results.push({
62655
- modelName,
62656
- inputMultiplier,
62657
- cachedInputMultiplier: cachedInput === "n/a" || cachedInput === "" ? null : Number.parseFloat(cachedInput) || null,
62658
- outputMultiplier
62659
- });
62660
- }
62661
- }
62662
- return results;
62663
- }
62664
- function parsePremiumMultiplierTable(html) {
62665
- const results = [];
62666
- const tableRowPattern = /<tr[^>]*>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]+)<\/td>\s*<\/tr>/gi;
62667
- for (const match of html.matchAll(tableRowPattern)) {
62668
- const modelName = cleanCellText(match[1]);
62669
- const multiplier = Number.parseFloat(match[2]);
62670
- if (modelName && !Number.isNaN(multiplier) && multiplier > 0) {
62671
- results.push({ modelName, multiplier });
62672
- }
62673
- }
62674
- return results;
62675
- }
62676
- function cleanCellText(text) {
62677
- return text.replace(/<[^>]*>/g, "").replace(/&[^;]+;/g, " ").trim();
62678
- }
62679
- function parseCopilotPricingMarkdown(markdown) {
62680
- const results = [];
62681
- const seenModels = /* @__PURE__ */ new Set();
62682
- const lines = markdown.split("\n");
62683
- let columnIndices = null;
62684
- for (const line of lines) {
62685
- const trimmed = line.trim();
62686
- if (!trimmed.startsWith("|")) continue;
62687
- if (/\|\s*Model\s/i.test(trimmed)) {
62688
- columnIndices = parseHeaderColumns(trimmed);
62689
- continue;
62690
- }
62691
- if (/^[\s|:-]+$/.test(trimmed) || !columnIndices) continue;
62692
- const entry = parseDataRow(trimmed, columnIndices);
62693
- if (entry && !seenModels.has(entry.modelName.toLowerCase())) {
62694
- seenModels.add(entry.modelName.toLowerCase());
62695
- results.push(entry);
62696
- }
62697
- }
62698
- return results;
62699
- }
62700
- function parseDataRow(line, columnIndices) {
62701
- const cells = splitMarkdownRow(line);
62702
- if (cells.length <= columnIndices.output) return null;
62703
- const modelName = cells[columnIndices.model].trim();
62704
- const inputPrice = parseDollarValue(cells[columnIndices.input]);
62705
- const cachedPrice = columnIndices.cached >= 0 ? parseDollarValue(cells[columnIndices.cached]) : null;
62706
- const outputPrice = parseDollarValue(cells[columnIndices.output]);
62707
- if (!modelName || inputPrice === null || outputPrice === null) return null;
62708
- return {
62709
- modelName,
62710
- inputMultiplier: inputPrice * PRICE_TO_MULTIPLIER,
62711
- cachedInputMultiplier: cachedPrice !== null ? cachedPrice * PRICE_TO_MULTIPLIER : null,
62712
- outputMultiplier: outputPrice * PRICE_TO_MULTIPLIER
62713
- };
62714
- }
62715
- function parseHeaderColumns(headerLine) {
62716
- const cells = splitMarkdownRow(headerLine).map((c) => c.trim().toLowerCase());
62717
- const model = cells.findIndex((c) => c === "model" || c === "model name");
62718
- const input = cells.findIndex(
62719
- (c) => (c === "input" || c === "input multiplier") && !c.includes("cached")
62720
- );
62721
- const cached2 = cells.findIndex(
62722
- (c) => c.includes("cached input") || c === "cached input multiplier"
62723
- );
62724
- const output = cells.findIndex(
62725
- (c) => (c === "output" || c === "output multiplier") && !c.includes("cached")
62726
- );
62727
- if (model < 0 || input < 0 || output < 0) {
62728
- return null;
62729
- }
62730
- return { model, input, cached: cached2 >= 0 ? cached2 : -1, output };
62731
- }
62732
- function splitMarkdownRow(line) {
62733
- const parts = line.split("|");
62734
- if (parts[0].trim() === "") parts.shift();
62735
- if (parts[parts.length - 1]?.trim() === "") parts.pop();
62736
- return parts;
62737
- }
62738
- function parseDollarValue(cell) {
62739
- if (!cell) return null;
62740
- const cleaned = cell.trim().replace(/[$,]/g, "");
62741
- if (cleaned.toLowerCase() === "n/a" || cleaned === "" || cleaned === "-") {
62742
- return null;
62743
- }
62744
- const value = Number.parseFloat(cleaned);
62745
- return Number.isNaN(value) ? null : value;
62746
- }
62747
- var TOKEN_UNIT_COSTS_URL, PREMIUM_MULTIPLIERS_URL, COPILOT_PRICING_URL, PRICE_TO_MULTIPLIER;
62748
- var init_pricing_scraper = __esm({
62749
- "packages/daemon/src/models/pricing-scraper.ts"() {
62750
- "use strict";
62751
- TOKEN_UNIT_COSTS_URL = "https://docs.github.com/en/billing/reference/costs-for-github-models";
62752
- PREMIUM_MULTIPLIERS_URL = "https://docs.github.com/en/copilot/reference/copilot-billing/request-based-billing-legacy/model-multipliers-for-annual-plans";
62753
- COPILOT_PRICING_URL = "https://docs.github.com/api/article/body?pathname=/en/copilot/reference/copilot-billing/models-and-pricing";
62754
- PRICE_TO_MULTIPLIER = 0.1;
62755
- }
62756
- });
62757
-
62758
- // packages/daemon/src/models/types.ts
62759
- function computeTierFromMultiplier(premiumMultiplier) {
62760
- if (premiumMultiplier === null) {
62761
- return "standard";
62762
- }
62763
- for (const [tier, range] of Object.entries(TIER_RANGES)) {
62764
- if (premiumMultiplier >= range.min && premiumMultiplier <= range.max) {
62765
- return tier;
62766
- }
62767
- }
62768
- return "ultra";
62769
- }
62770
- var TIER_RANGES, TOKEN_UNIT_PRICE;
62771
- var init_types = __esm({
62772
- "packages/daemon/src/models/types.ts"() {
62773
- "use strict";
62774
- TIER_RANGES = {
62775
- trivial: { min: 0, max: 0.33 },
62776
- fast: { min: 0.34, max: 1 },
62777
- standard: { min: 1.1, max: 5 },
62778
- premium: { min: 5.1, max: 15 },
62779
- ultra: { min: 15.1, max: Number.POSITIVE_INFINITY }
62780
- };
62781
- TOKEN_UNIT_PRICE = 1e-5;
62782
- }
62783
- });
62784
-
62785
- // packages/daemon/src/models/registry.ts
62786
- function stripVendorPrefix(id) {
62787
- const slashIndex = id.indexOf("/");
62788
- return slashIndex >= 0 ? id.slice(slashIndex + 1) : id;
62789
- }
62790
- function normalizeModelName(name) {
62791
- return stripVendorPrefix(name).toLowerCase().replace(/^openai\s+/i, "").replace(/\s+/g, "-").replace(/[^a-z0-9.\-]/g, "").trim();
62792
- }
62793
- async function fetchCatalogIntoMap(modelMap, result, logger2) {
62794
- try {
62795
- const catalogModels = await fetchModelCatalog();
62796
- result.catalogFetched = true;
62797
- for (const m of catalogModels) {
62798
- const key = normalizeModelName(m.id);
62799
- const id = stripVendorPrefix(m.id);
62800
- modelMap.set(key, { id, displayName: m.displayName, available: true });
62801
- }
62802
- } catch (error51) {
62803
- const msg = error51 instanceof Error ? error51.message : String(error51);
62804
- result.errors.push(`Catalog fetch failed: ${msg}`);
62805
- logger2?.warn(`Model catalog fetch failed: ${msg}`);
62806
- }
62807
- }
62808
- async function scrapeTokenPricingIntoMap(modelMap, result, logger2) {
62809
- try {
62810
- const tokenPricing = await scrapeTokenUnitPricing();
62811
- result.tokenPricingScraped = true;
62812
- for (const tp of tokenPricing) {
62813
- const key = normalizeModelName(tp.modelName);
62814
- const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
62815
- if (existing) {
62816
- existing.tokenInputMultiplier = tp.inputMultiplier;
62817
- existing.tokenOutputMultiplier = tp.outputMultiplier;
62818
- existing.cachedInputMultiplier = tp.cachedInputMultiplier;
62819
- } else {
62820
- modelMap.set(key, {
62821
- id: key,
62822
- displayName: tp.modelName,
62823
- tokenInputMultiplier: tp.inputMultiplier,
62824
- tokenOutputMultiplier: tp.outputMultiplier,
62825
- cachedInputMultiplier: tp.cachedInputMultiplier,
62826
- available: true
62827
- });
62828
- }
62829
- }
62830
- } catch (error51) {
62831
- const msg = error51 instanceof Error ? error51.message : String(error51);
62832
- result.errors.push(`Token pricing scrape failed: ${msg}`);
62833
- logger2?.warn(`Token pricing scrape failed: ${msg}`);
62834
- }
62835
- }
62836
- async function scrapePremiumPricingIntoMap(modelMap, result, logger2) {
62837
- try {
62838
- const premiumPricing = await scrapePremiumRequestPricing();
62839
- result.premiumPricingScraped = true;
62840
- for (const pp of premiumPricing) {
62841
- const key = normalizeModelName(pp.modelName);
62842
- const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
62843
- if (existing) {
62844
- existing.premiumMultiplier = pp.multiplier;
62845
- } else {
62846
- modelMap.set(key, {
62847
- id: key,
62848
- displayName: pp.modelName,
62849
- premiumMultiplier: pp.multiplier,
62850
- available: true
62851
- });
62852
- }
62853
- }
62854
- } catch (error51) {
62855
- const msg = error51 instanceof Error ? error51.message : String(error51);
62856
- result.errors.push(`Premium pricing scrape failed: ${msg}`);
62857
- logger2?.warn(`Premium pricing scrape failed: ${msg}`);
62858
- }
62859
- }
62860
- async function scrapeCopilotPricingIntoMap(modelMap, result, logger2) {
62861
- try {
62862
- const copilotPricing = await scrapeCopilotPricing();
62863
- result.copilotPricingScraped = true;
62864
- for (const cp of copilotPricing) {
62865
- const key = normalizeModelName(cp.modelName);
62866
- const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
62867
- if (existing) {
62868
- existing.tokenInputMultiplier = cp.inputMultiplier;
62869
- existing.tokenOutputMultiplier = cp.outputMultiplier;
62870
- if (cp.cachedInputMultiplier !== null) {
62871
- existing.cachedInputMultiplier = cp.cachedInputMultiplier;
62872
- }
62873
- } else {
62874
- modelMap.set(key, {
62875
- id: key,
62876
- displayName: cp.modelName,
62877
- tokenInputMultiplier: cp.inputMultiplier,
62878
- tokenOutputMultiplier: cp.outputMultiplier,
62879
- cachedInputMultiplier: cp.cachedInputMultiplier,
62880
- available: true
62881
- });
62882
- }
62883
- }
62884
- } catch (error51) {
62885
- const msg = error51 instanceof Error ? error51.message : String(error51);
62886
- result.errors.push(`Copilot pricing scrape failed: ${msg}`);
62887
- logger2?.warn(`Copilot pricing scrape failed: ${msg}`);
62888
- }
62889
- }
62890
- async function refreshModelPricing(logger2) {
62891
- const result = {
62892
- modelsUpdated: 0,
62893
- catalogFetched: false,
62894
- tokenPricingScraped: false,
62895
- premiumPricingScraped: false,
62896
- copilotPricingScraped: false,
62897
- errors: []
62898
- };
62899
- const modelMap = /* @__PURE__ */ new Map();
62900
- await fetchCatalogIntoMap(modelMap, result, logger2);
62901
- await scrapeTokenPricingIntoMap(modelMap, result, logger2);
62902
- await scrapeCopilotPricingIntoMap(modelMap, result, logger2);
62903
- await scrapePremiumPricingIntoMap(modelMap, result, logger2);
62904
- if (!result.catalogFetched && !result.tokenPricingScraped && !result.premiumPricingScraped && !result.copilotPricingScraped) {
62905
- logger2?.warn("All pricing sources failed, no models available");
62906
- return result;
62907
- }
62908
- const db = await getDatabase();
62909
- const now = nowIso();
62910
- for (const model of modelMap.values()) {
62911
- if (model.tokenInputMultiplier == null) {
62912
- continue;
62913
- }
62914
- const tier = computeTierFromMultiplier(model.premiumMultiplier ?? null);
62915
- await upsertModel(db, {
62916
- id: model.id,
62917
- displayName: model.displayName,
62918
- premiumMultiplier: model.premiumMultiplier ?? null,
62919
- tokenInputMultiplier: model.tokenInputMultiplier,
62920
- tokenOutputMultiplier: model.tokenOutputMultiplier ?? null,
62921
- cachedInputMultiplier: model.cachedInputMultiplier ?? null,
62922
- tier,
62923
- available: model.available ?? true,
62924
- updatedAt: now
62925
- });
62926
- result.modelsUpdated++;
62927
- }
62928
- return result;
62929
- }
62930
- async function getModelsForTier(tier) {
62931
- const db = await getDatabase();
62932
- const result = await db.execute({
62933
- sql: "SELECT * FROM model_pricing WHERE tier = ? AND available = 1 ORDER BY premium_multiplier ASC NULLS LAST",
62934
- args: [tier]
62935
- });
62936
- return result.rows.map(rowToModelPricing);
62937
- }
62938
- async function getCheapestInTier(tier) {
62939
- const models = await getModelsForTier(tier);
62940
- return models[0] ?? null;
62941
- }
62942
- async function getModelPricing(modelId) {
62943
- const db = await getDatabase();
62944
- const result = await db.execute({
62945
- sql: "SELECT * FROM model_pricing WHERE id = ?",
62946
- args: [modelId]
62947
- });
62948
- if (result.rows.length > 0) {
62949
- return rowToModelPricing(result.rows[0]);
62950
- }
62951
- const allModels = await db.execute(
62952
- "SELECT * FROM model_pricing WHERE token_input_multiplier IS NOT NULL ORDER BY length(id) DESC"
62953
- );
62954
- for (const row of allModels.rows) {
62955
- const storedId = asString(row.id);
62956
- if (modelId.startsWith(storedId) || storedId.startsWith(modelId)) {
62957
- return rowToModelPricing(row);
62958
- }
62959
- }
62960
- return null;
62961
- }
62962
- async function getCheapestAvailableModel() {
62963
- const tiers = ["trivial", "fast", "standard", "premium", "ultra"];
62964
- for (const tier of tiers) {
62965
- const model = await getCheapestInTier(tier);
62966
- if (model) {
62967
- return model;
62968
- }
62969
- }
62970
- return null;
62971
- }
62972
- function calculateTokenUnitCost(inputTokens, outputTokens, inputMultiplier, outputMultiplier) {
62973
- if (inputMultiplier === null || outputMultiplier === null) {
62974
- return 0;
62975
- }
62976
- const tokenUnits = inputTokens * inputMultiplier + outputTokens * outputMultiplier;
62977
- return tokenUnits * TOKEN_UNIT_PRICE;
62978
- }
62979
- function getNextTierUp(tier) {
62980
- const order = ["trivial", "fast", "standard", "premium", "ultra"];
62981
- const idx = order.indexOf(tier);
62982
- if (idx < 0 || idx >= order.length - 1) {
62983
- return null;
62984
- }
62985
- return order[idx + 1];
62986
- }
62987
- async function upsertModel(db, model) {
62988
- await db.execute({
62989
- sql: `INSERT INTO model_pricing (id, display_name, premium_multiplier, token_input_multiplier, token_output_multiplier, cached_input_multiplier, tier, available, updated_at)
62990
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
62991
- ON CONFLICT(id) DO UPDATE SET
62992
- display_name = excluded.display_name,
62993
- premium_multiplier = COALESCE(excluded.premium_multiplier, model_pricing.premium_multiplier),
62994
- token_input_multiplier = COALESCE(excluded.token_input_multiplier, model_pricing.token_input_multiplier),
62995
- token_output_multiplier = COALESCE(excluded.token_output_multiplier, model_pricing.token_output_multiplier),
62996
- cached_input_multiplier = COALESCE(excluded.cached_input_multiplier, model_pricing.cached_input_multiplier),
62997
- tier = excluded.tier,
62998
- available = excluded.available,
62999
- updated_at = excluded.updated_at`,
63000
- args: [
63001
- model.id,
63002
- model.displayName,
63003
- model.premiumMultiplier,
63004
- model.tokenInputMultiplier,
63005
- model.tokenOutputMultiplier,
63006
- model.cachedInputMultiplier,
63007
- model.tier,
63008
- model.available ? 1 : 0,
63009
- model.updatedAt
63010
- ]
63011
- });
63012
- }
63013
- function rowToModelPricing(row) {
63014
- return {
63015
- id: asString(row.id),
63016
- displayName: asString(row.display_name),
63017
- premiumMultiplier: asNullableNumber(row.premium_multiplier),
63018
- tokenInputMultiplier: asNullableNumber(row.token_input_multiplier),
63019
- tokenOutputMultiplier: asNullableNumber(row.token_output_multiplier),
63020
- cachedInputMultiplier: asNullableNumber(row.cached_input_multiplier),
63021
- tier: asString(row.tier),
63022
- available: asNumber(row.available) === 1,
63023
- updatedAt: asString(row.updated_at)
63024
- };
63025
- }
63026
- function findClosestKey(map2, targetKey) {
63027
- for (const [key, value] of map2) {
63028
- if (key.includes(targetKey) || targetKey.includes(key)) {
63029
- return value;
63030
- }
63031
- }
63032
- return void 0;
63033
- }
63034
- var init_registry = __esm({
63035
- "packages/daemon/src/models/registry.ts"() {
63036
- "use strict";
63037
- init_db();
63038
- init_catalog();
63039
- init_pricing_scraper();
63040
- init_types();
63041
- }
63042
- });
63043
-
63044
62209
  // node_modules/grammy/out/filter.js
63045
62210
  var require_filter = __commonJS({
63046
62211
  "node_modules/grammy/out/filter.js"(exports2) {
@@ -77767,11 +76932,344 @@ var TypedEventBus = class extends EventEmitter {
77767
76932
  };
77768
76933
  var eventBus = new TypedEventBus();
77769
76934
 
77770
- // packages/daemon/src/store/index.ts
77771
- init_db();
76935
+ // packages/daemon/src/store/db.ts
76936
+ init_paths();
76937
+ import { mkdir } from "node:fs/promises";
76938
+ import { dirname } from "node:path";
76939
+ import { pathToFileURL } from "node:url";
76940
+ import { createClient } from "@libsql/client";
76941
+ var MIGRATIONS = [
76942
+ {
76943
+ version: 1,
76944
+ name: "create-store-schema",
76945
+ statements: [
76946
+ `CREATE TABLE IF NOT EXISTS squads (
76947
+ id TEXT PRIMARY KEY,
76948
+ name TEXT NOT NULL,
76949
+ repo_url TEXT NOT NULL,
76950
+ repo_owner TEXT NOT NULL,
76951
+ repo_name TEXT NOT NULL,
76952
+ status TEXT NOT NULL,
76953
+ config TEXT NOT NULL,
76954
+ created_at TEXT NOT NULL,
76955
+ updated_at TEXT NOT NULL,
76956
+ UNIQUE (repo_owner, repo_name)
76957
+ )`,
76958
+ `CREATE TABLE IF NOT EXISTS squad_members (
76959
+ id TEXT PRIMARY KEY,
76960
+ squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
76961
+ role TEXT NOT NULL,
76962
+ name TEXT NOT NULL,
76963
+ system_prompt TEXT NOT NULL,
76964
+ model TEXT,
76965
+ created_at TEXT NOT NULL
76966
+ )`,
76967
+ `CREATE TABLE IF NOT EXISTS objectives (
76968
+ id TEXT PRIMARY KEY,
76969
+ squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
76970
+ description TEXT NOT NULL,
76971
+ status TEXT NOT NULL,
76972
+ plan TEXT,
76973
+ revision_count INTEGER NOT NULL DEFAULT 0,
76974
+ branch TEXT,
76975
+ pr_url TEXT,
76976
+ created_at TEXT NOT NULL,
76977
+ updated_at TEXT NOT NULL
76978
+ )`,
76979
+ `CREATE TABLE IF NOT EXISTS tasks (
76980
+ id TEXT PRIMARY KEY,
76981
+ objective_id TEXT NOT NULL REFERENCES objectives(id) ON DELETE CASCADE,
76982
+ assignee_id TEXT REFERENCES squad_members(id) ON DELETE SET NULL,
76983
+ title TEXT NOT NULL,
76984
+ description TEXT NOT NULL,
76985
+ status TEXT NOT NULL,
76986
+ result TEXT,
76987
+ created_at TEXT NOT NULL,
76988
+ updated_at TEXT NOT NULL
76989
+ )`,
76990
+ `CREATE TABLE IF NOT EXISTS conversations (
76991
+ id TEXT PRIMARY KEY,
76992
+ title TEXT,
76993
+ source TEXT NOT NULL,
76994
+ created_at TEXT NOT NULL,
76995
+ updated_at TEXT NOT NULL
76996
+ )`,
76997
+ `CREATE TABLE IF NOT EXISTS messages (
76998
+ id TEXT PRIMARY KEY,
76999
+ conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
77000
+ role TEXT NOT NULL,
77001
+ content TEXT NOT NULL,
77002
+ model TEXT,
77003
+ input_tokens INTEGER,
77004
+ output_tokens INTEGER,
77005
+ created_at TEXT NOT NULL
77006
+ )`,
77007
+ `CREATE TABLE IF NOT EXISTS inbox (
77008
+ id TEXT PRIMARY KEY,
77009
+ squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
77010
+ objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
77011
+ type TEXT NOT NULL,
77012
+ title TEXT NOT NULL,
77013
+ content TEXT NOT NULL,
77014
+ status TEXT NOT NULL,
77015
+ reply TEXT,
77016
+ created_at TEXT NOT NULL,
77017
+ updated_at TEXT NOT NULL
77018
+ )`,
77019
+ `CREATE TABLE IF NOT EXISTS schedules (
77020
+ id TEXT PRIMARY KEY,
77021
+ name TEXT NOT NULL,
77022
+ cron_expression TEXT NOT NULL,
77023
+ prompt TEXT NOT NULL,
77024
+ enabled INTEGER NOT NULL DEFAULT 1,
77025
+ last_run_at TEXT,
77026
+ next_run_at TEXT,
77027
+ created_at TEXT NOT NULL,
77028
+ updated_at TEXT NOT NULL
77029
+ )`,
77030
+ `CREATE TABLE IF NOT EXISTS token_usage (
77031
+ id TEXT PRIMARY KEY,
77032
+ squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
77033
+ agent_id TEXT,
77034
+ model TEXT NOT NULL,
77035
+ input_tokens INTEGER NOT NULL,
77036
+ output_tokens INTEGER NOT NULL,
77037
+ cost REAL NOT NULL,
77038
+ created_at TEXT NOT NULL
77039
+ )`,
77040
+ `CREATE TABLE IF NOT EXISTS activity (
77041
+ id TEXT PRIMARY KEY,
77042
+ squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
77043
+ objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
77044
+ event TEXT NOT NULL,
77045
+ description TEXT NOT NULL,
77046
+ metadata TEXT,
77047
+ created_at TEXT NOT NULL
77048
+ )`,
77049
+ `CREATE TABLE IF NOT EXISTS agent_history (
77050
+ id TEXT PRIMARY KEY,
77051
+ agent_id TEXT NOT NULL,
77052
+ squad_id TEXT REFERENCES squads(id) ON DELETE SET NULL,
77053
+ content TEXT NOT NULL,
77054
+ created_at TEXT NOT NULL
77055
+ )`,
77056
+ `CREATE TABLE IF NOT EXISTS settings (
77057
+ key TEXT PRIMARY KEY,
77058
+ value TEXT
77059
+ )`,
77060
+ "CREATE INDEX IF NOT EXISTS idx_squad_members_squad_id ON squad_members(squad_id)",
77061
+ "CREATE INDEX IF NOT EXISTS idx_objectives_squad_id ON objectives(squad_id)",
77062
+ "CREATE INDEX IF NOT EXISTS idx_objectives_status ON objectives(status)",
77063
+ "CREATE INDEX IF NOT EXISTS idx_tasks_objective_id ON tasks(objective_id)",
77064
+ "CREATE INDEX IF NOT EXISTS idx_tasks_assignee_id ON tasks(assignee_id)",
77065
+ "CREATE INDEX IF NOT EXISTS idx_messages_conversation_id_created_at ON messages(conversation_id, created_at)",
77066
+ "CREATE INDEX IF NOT EXISTS idx_inbox_status_created_at ON inbox(status, created_at)",
77067
+ "CREATE INDEX IF NOT EXISTS idx_inbox_squad_id ON inbox(squad_id)",
77068
+ "CREATE INDEX IF NOT EXISTS idx_inbox_objective_id ON inbox(objective_id)",
77069
+ "CREATE INDEX IF NOT EXISTS idx_schedules_enabled_next_run_at ON schedules(enabled, next_run_at)",
77070
+ "CREATE INDEX IF NOT EXISTS idx_token_usage_created_at ON token_usage(created_at)",
77071
+ "CREATE INDEX IF NOT EXISTS idx_token_usage_squad_id ON token_usage(squad_id)",
77072
+ "CREATE INDEX IF NOT EXISTS idx_token_usage_agent_id ON token_usage(agent_id)",
77073
+ "CREATE INDEX IF NOT EXISTS idx_token_usage_model ON token_usage(model)",
77074
+ "CREATE INDEX IF NOT EXISTS idx_activity_created_at ON activity(created_at)",
77075
+ "CREATE INDEX IF NOT EXISTS idx_activity_squad_id ON activity(squad_id)",
77076
+ "CREATE INDEX IF NOT EXISTS idx_activity_objective_id ON activity(objective_id)",
77077
+ "CREATE INDEX IF NOT EXISTS idx_agent_history_agent_id_created_at ON agent_history(agent_id, created_at)"
77078
+ ]
77079
+ },
77080
+ {
77081
+ version: 2,
77082
+ name: "add-model-pricing-and-dual-costs",
77083
+ statements: [
77084
+ `CREATE TABLE IF NOT EXISTS model_pricing (
77085
+ id TEXT PRIMARY KEY,
77086
+ display_name TEXT NOT NULL,
77087
+ premium_multiplier REAL,
77088
+ token_input_multiplier REAL,
77089
+ token_output_multiplier REAL,
77090
+ cached_input_multiplier REAL,
77091
+ tier TEXT NOT NULL,
77092
+ available INTEGER NOT NULL DEFAULT 1,
77093
+ updated_at TEXT NOT NULL
77094
+ )`,
77095
+ "CREATE INDEX IF NOT EXISTS idx_model_pricing_tier ON model_pricing(tier)",
77096
+ "CREATE INDEX IF NOT EXISTS idx_model_pricing_available ON model_pricing(available)",
77097
+ "ALTER TABLE token_usage ADD COLUMN premium_request_cost REAL",
77098
+ "ALTER TABLE token_usage ADD COLUMN token_unit_cost REAL"
77099
+ ]
77100
+ },
77101
+ {
77102
+ version: 3,
77103
+ name: "add-squad-instances",
77104
+ statements: [
77105
+ `CREATE TABLE IF NOT EXISTS squad_instances (
77106
+ id TEXT PRIMARY KEY,
77107
+ squad_id TEXT NOT NULL REFERENCES squads(id) ON DELETE CASCADE,
77108
+ objective_id TEXT REFERENCES objectives(id) ON DELETE SET NULL,
77109
+ status TEXT NOT NULL DEFAULT 'queued',
77110
+ branch TEXT,
77111
+ worktree_path TEXT,
77112
+ created_at TEXT NOT NULL,
77113
+ started_at TEXT,
77114
+ completed_at TEXT,
77115
+ error TEXT
77116
+ )`,
77117
+ "CREATE INDEX IF NOT EXISTS idx_squad_instances_squad_status ON squad_instances(squad_id, status)",
77118
+ "CREATE INDEX IF NOT EXISTS idx_squad_instances_status ON squad_instances(status)",
77119
+ "CREATE INDEX IF NOT EXISTS idx_squad_instances_objective_id ON squad_instances(objective_id)"
77120
+ ]
77121
+ },
77122
+ {
77123
+ version: 4,
77124
+ name: "denormalize-usage-names",
77125
+ statements: [
77126
+ "ALTER TABLE token_usage ADD COLUMN squad_name TEXT",
77127
+ "ALTER TABLE token_usage ADD COLUMN agent_name TEXT",
77128
+ `UPDATE token_usage SET
77129
+ squad_name = (SELECT s.name FROM squads s WHERE s.id = token_usage.squad_id),
77130
+ agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
77131
+ WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
77132
+ ]
77133
+ },
77134
+ {
77135
+ version: 5,
77136
+ name: "add-squad-soft-delete",
77137
+ statements: ["ALTER TABLE squads ADD COLUMN deleted_at TEXT"]
77138
+ }
77139
+ ];
77140
+ var client = null;
77141
+ var initPromise = null;
77142
+ var defaultConnectionOptions = {};
77143
+ var generateId = () => crypto.randomUUID();
77144
+ var nowIso = () => (/* @__PURE__ */ new Date()).toISOString();
77145
+ function asString(value) {
77146
+ if (typeof value === "string") {
77147
+ return value;
77148
+ }
77149
+ if (value === null || value === void 0) {
77150
+ throw new Error("Expected string value but received null or undefined");
77151
+ }
77152
+ return String(value);
77153
+ }
77154
+ function asNullableString(value) {
77155
+ if (value === null || value === void 0) {
77156
+ return null;
77157
+ }
77158
+ return typeof value === "string" ? value : String(value);
77159
+ }
77160
+ function asNumber(value) {
77161
+ if (typeof value === "number") {
77162
+ return value;
77163
+ }
77164
+ if (typeof value === "bigint") {
77165
+ return Number(value);
77166
+ }
77167
+ if (typeof value === "string") {
77168
+ return Number(value);
77169
+ }
77170
+ throw new Error(`Expected numeric value but received ${typeof value}`);
77171
+ }
77172
+ function asNullableNumber(value) {
77173
+ if (value === null || value === void 0) {
77174
+ return null;
77175
+ }
77176
+ return asNumber(value);
77177
+ }
77178
+ function asBoolean(value) {
77179
+ return asNumber(value) === 1;
77180
+ }
77181
+ function toSqliteBoolean(value) {
77182
+ return value ? 1 : 0;
77183
+ }
77184
+ function parseJson(value) {
77185
+ if (typeof value !== "string") {
77186
+ return value;
77187
+ }
77188
+ return JSON.parse(value);
77189
+ }
77190
+ function serializeJson(value) {
77191
+ return JSON.stringify(value);
77192
+ }
77193
+ async function initDatabase() {
77194
+ if (client && !client.closed) {
77195
+ return client;
77196
+ }
77197
+ if (initPromise) {
77198
+ return initPromise;
77199
+ }
77200
+ initPromise = initializeDatabase(defaultConnectionOptions);
77201
+ try {
77202
+ client = await initPromise;
77203
+ return client;
77204
+ } finally {
77205
+ initPromise = null;
77206
+ }
77207
+ }
77208
+ async function getDatabase() {
77209
+ return initDatabase();
77210
+ }
77211
+ async function initializeDatabase(options2 = {}) {
77212
+ const url2 = await resolveDatabaseUrl(options2);
77213
+ const databaseClient = createClient({ url: url2 });
77214
+ await databaseClient.execute("PRAGMA foreign_keys = ON");
77215
+ await databaseClient.execute("PRAGMA journal_mode = WAL");
77216
+ await ensureMigrationTable(databaseClient);
77217
+ await applyMigrations(databaseClient);
77218
+ return databaseClient;
77219
+ }
77220
+ async function resolveDatabaseUrl(options2) {
77221
+ if (options2.url) {
77222
+ return options2.url;
77223
+ }
77224
+ const databasePath = options2.path ?? DB_PATH;
77225
+ await mkdir(dirname(databasePath), { recursive: true });
77226
+ return pathToFileURL(databasePath).href;
77227
+ }
77228
+ async function ensureMigrationTable(databaseClient) {
77229
+ await databaseClient.executeMultiple(`
77230
+ CREATE TABLE IF NOT EXISTS schema_migrations (
77231
+ version INTEGER PRIMARY KEY,
77232
+ name TEXT NOT NULL,
77233
+ applied_at TEXT NOT NULL
77234
+ );
77235
+ `);
77236
+ }
77237
+ async function applyMigrations(databaseClient) {
77238
+ const appliedVersions = await getAppliedVersions(databaseClient);
77239
+ for (const migration of MIGRATIONS) {
77240
+ if (appliedVersions.has(migration.version)) {
77241
+ continue;
77242
+ }
77243
+ const transaction = await databaseClient.transaction("write");
77244
+ try {
77245
+ for (const statement of migration.statements) {
77246
+ await transaction.execute(statement);
77247
+ }
77248
+ await transaction.execute({
77249
+ sql: "INSERT INTO schema_migrations (version, name, applied_at) VALUES (?, ?, ?)",
77250
+ args: [migration.version, migration.name, nowIso()]
77251
+ });
77252
+ await transaction.commit();
77253
+ } catch (error51) {
77254
+ if (!transaction.closed) {
77255
+ await transaction.rollback();
77256
+ }
77257
+ throw error51;
77258
+ } finally {
77259
+ if (!transaction.closed) {
77260
+ transaction.close();
77261
+ }
77262
+ }
77263
+ }
77264
+ }
77265
+ async function getAppliedVersions(databaseClient) {
77266
+ const result = await databaseClient.execute(
77267
+ "SELECT version FROM schema_migrations ORDER BY version ASC"
77268
+ );
77269
+ return new Set(result.rows.map((row) => asNumber(row.version)));
77270
+ }
77772
77271
 
77773
77272
  // packages/daemon/src/store/squads.ts
77774
- init_db();
77775
77273
  async function createSquad(data, db) {
77776
77274
  const database = db ?? await getDatabase();
77777
77275
  const timestamp = nowIso();
@@ -78027,7 +77525,6 @@ function mapMember(row) {
78027
77525
  }
78028
77526
 
78029
77527
  // packages/daemon/src/store/conversations.ts
78030
- init_db();
78031
77528
  async function createConversation(source, title, db) {
78032
77529
  const database = db ?? await getDatabase();
78033
77530
  const createdAt = nowIso();
@@ -78146,7 +77643,6 @@ function mapMessage(row) {
78146
77643
  }
78147
77644
 
78148
77645
  // packages/daemon/src/store/inbox.ts
78149
- init_db();
78150
77646
  async function createInboxItem(data, db) {
78151
77647
  const database = db ?? await getDatabase();
78152
77648
  const timestamp = nowIso();
@@ -78250,7 +77746,6 @@ function mapInboxItem(row) {
78250
77746
 
78251
77747
  // packages/daemon/src/store/schedules.ts
78252
77748
  var import_cron_parser = __toESM(require_dist(), 1);
78253
- init_db();
78254
77749
  var parseExpression = import_cron_parser.CronExpressionParser.parse;
78255
77750
  async function createSchedule(data, db) {
78256
77751
  const database = db ?? await getDatabase();
@@ -78389,7 +77884,6 @@ function mapSchedule(row) {
78389
77884
  }
78390
77885
 
78391
77886
  // packages/daemon/src/store/token-usage.ts
78392
- init_db();
78393
77887
  async function recordUsage(data, db) {
78394
77888
  const database = db ?? await getDatabase();
78395
77889
  const usage = {
@@ -78519,7 +78013,6 @@ async function getUsageRecords(params = {}, db) {
78519
78013
  }
78520
78014
 
78521
78015
  // packages/daemon/src/store/activity.ts
78522
- init_db();
78523
78016
  async function logActivity(data, db) {
78524
78017
  const database = db ?? await getDatabase();
78525
78018
  const activity = {
@@ -78575,7 +78068,6 @@ function mapActivity(row) {
78575
78068
  }
78576
78069
 
78577
78070
  // packages/daemon/src/store/agent-history.ts
78578
- init_db();
78579
78071
  async function appendHistory(agentId, squadId, content, db) {
78580
78072
  const database = db ?? await getDatabase();
78581
78073
  const entry = {
@@ -78611,7 +78103,6 @@ function mapAgentHistory(row) {
78611
78103
  }
78612
78104
 
78613
78105
  // packages/daemon/src/store/objectives.ts
78614
- init_db();
78615
78106
  async function createObjective(squadId, description, db) {
78616
78107
  const database = db ?? await getDatabase();
78617
78108
  const timestamp = nowIso();
@@ -78804,7 +78295,6 @@ function mapTask(row) {
78804
78295
  }
78805
78296
 
78806
78297
  // packages/daemon/src/store/instances.ts
78807
- init_db();
78808
78298
  async function createInstance(input, db) {
78809
78299
  const database = db ?? await getDatabase();
78810
78300
  const instance = {
@@ -80113,7 +79603,6 @@ function emitInstanceEvent(event, instance) {
80113
79603
  }
80114
79604
 
80115
79605
  // packages/daemon/src/api/routes/squads.ts
80116
- init_db();
80117
79606
  var router7 = (0, import_express7.Router)();
80118
79607
  var DEFAULT_CONFIG = {
80119
79608
  prMode: "draft-pr",
@@ -81372,10 +80861,471 @@ function ensureDataDirectories() {
81372
80861
  }
81373
80862
  }
81374
80863
 
81375
- // packages/daemon/src/models/index.ts
81376
- init_catalog();
81377
- init_registry();
81378
- init_types();
80864
+ // packages/daemon/src/models/catalog.ts
80865
+ import { execFileSync } from "node:child_process";
80866
+ var CATALOG_URL = "https://models.github.ai/catalog/models";
80867
+ function resolveGitHubToken() {
80868
+ const envToken = process.env.GITHUB_TOKEN?.trim();
80869
+ if (envToken && envToken.length > 0) {
80870
+ return envToken;
80871
+ }
80872
+ try {
80873
+ const token = execFileSync("gh", ["auth", "token"], {
80874
+ encoding: "utf8",
80875
+ stdio: ["ignore", "pipe", "pipe"]
80876
+ }).trim();
80877
+ return token.length > 0 ? token : void 0;
80878
+ } catch {
80879
+ return void 0;
80880
+ }
80881
+ }
80882
+ async function fetchModelCatalog() {
80883
+ const token = resolveGitHubToken();
80884
+ if (!token) {
80885
+ throw new Error("No GitHub token available for model catalog fetch");
80886
+ }
80887
+ const response = await fetch(CATALOG_URL, {
80888
+ headers: {
80889
+ Accept: "application/json",
80890
+ Authorization: `Bearer ${token}`,
80891
+ "X-GitHub-Api-Version": "2024-12-01"
80892
+ }
80893
+ });
80894
+ if (!response.ok) {
80895
+ throw new Error(`Model catalog fetch failed: ${response.status} ${response.statusText}`);
80896
+ }
80897
+ const data = await response.json();
80898
+ if (!Array.isArray(data)) {
80899
+ throw new Error("Model catalog response is not an array");
80900
+ }
80901
+ const models = [];
80902
+ for (const entry of data) {
80903
+ const id = entry.id ?? entry.name;
80904
+ const displayName = entry.friendly_name ?? entry.name ?? id;
80905
+ if (id && typeof id === "string") {
80906
+ models.push({ id, displayName: displayName ?? id });
80907
+ }
80908
+ }
80909
+ return models;
80910
+ }
80911
+
80912
+ // packages/daemon/src/models/pricing-scraper.ts
80913
+ var TOKEN_UNIT_COSTS_URL = "https://docs.github.com/en/billing/reference/costs-for-github-models";
80914
+ var PREMIUM_MULTIPLIERS_URL = "https://docs.github.com/en/copilot/reference/copilot-billing/request-based-billing-legacy/model-multipliers-for-annual-plans";
80915
+ var COPILOT_PRICING_URL = "https://docs.github.com/api/article/body?pathname=/en/copilot/reference/copilot-billing/models-and-pricing";
80916
+ var PRICE_TO_MULTIPLIER = 0.1;
80917
+ async function scrapeTokenUnitPricing() {
80918
+ const html = await fetchPage(TOKEN_UNIT_COSTS_URL);
80919
+ return parseTokenUnitTable(html);
80920
+ }
80921
+ async function scrapeCopilotPricing() {
80922
+ const markdown = await fetchMarkdown(COPILOT_PRICING_URL);
80923
+ return parseCopilotPricingMarkdown(markdown);
80924
+ }
80925
+ async function scrapePremiumRequestPricing() {
80926
+ const html = await fetchPage(PREMIUM_MULTIPLIERS_URL);
80927
+ return parsePremiumMultiplierTable(html);
80928
+ }
80929
+ async function fetchPage(url2) {
80930
+ const response = await fetch(url2, {
80931
+ headers: {
80932
+ Accept: "text/html",
80933
+ "User-Agent": "IO-Daemon/4.0 (pricing-refresh)"
80934
+ },
80935
+ redirect: "follow"
80936
+ });
80937
+ if (!response.ok) {
80938
+ throw new Error(`Failed to fetch ${url2}: ${response.status} ${response.statusText}`);
80939
+ }
80940
+ return response.text();
80941
+ }
80942
+ async function fetchMarkdown(url2) {
80943
+ const response = await fetch(url2, {
80944
+ headers: {
80945
+ Accept: "text/markdown, text/plain, */*",
80946
+ "User-Agent": "IO-Daemon/4.0 (pricing-refresh)"
80947
+ },
80948
+ redirect: "follow"
80949
+ });
80950
+ if (!response.ok) {
80951
+ throw new Error(`Failed to fetch ${url2}: ${response.status} ${response.statusText}`);
80952
+ }
80953
+ return response.text();
80954
+ }
80955
+ function parseTokenUnitTable(html) {
80956
+ const results = [];
80957
+ const tableRowPattern = /<tr[^>]*>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]*)<\/td>\s*<td[^>]*>([^<]+)<\/td>/gi;
80958
+ for (const match of html.matchAll(tableRowPattern)) {
80959
+ const modelName = cleanCellText(match[1]);
80960
+ const inputMultiplier = Number.parseFloat(match[2]);
80961
+ const cachedInput = match[3].trim().toLowerCase();
80962
+ const outputMultiplier = Number.parseFloat(match[4]);
80963
+ if (modelName && !Number.isNaN(inputMultiplier) && !Number.isNaN(outputMultiplier)) {
80964
+ results.push({
80965
+ modelName,
80966
+ inputMultiplier,
80967
+ cachedInputMultiplier: cachedInput === "n/a" || cachedInput === "" ? null : Number.parseFloat(cachedInput) || null,
80968
+ outputMultiplier
80969
+ });
80970
+ }
80971
+ }
80972
+ return results;
80973
+ }
80974
+ function parsePremiumMultiplierTable(html) {
80975
+ const results = [];
80976
+ const tableRowPattern = /<tr[^>]*>\s*<td[^>]*>([^<]+)<\/td>\s*<td[^>]*>([^<]+)<\/td>\s*<\/tr>/gi;
80977
+ for (const match of html.matchAll(tableRowPattern)) {
80978
+ const modelName = cleanCellText(match[1]);
80979
+ const multiplier = Number.parseFloat(match[2]);
80980
+ if (modelName && !Number.isNaN(multiplier) && multiplier > 0) {
80981
+ results.push({ modelName, multiplier });
80982
+ }
80983
+ }
80984
+ return results;
80985
+ }
80986
+ function cleanCellText(text) {
80987
+ return text.replace(/<[^>]*>/g, "").replace(/&[^;]+;/g, " ").trim();
80988
+ }
80989
+ function parseCopilotPricingMarkdown(markdown) {
80990
+ const results = [];
80991
+ const seenModels = /* @__PURE__ */ new Set();
80992
+ const lines = markdown.split("\n");
80993
+ let columnIndices = null;
80994
+ for (const line of lines) {
80995
+ const trimmed = line.trim();
80996
+ if (!trimmed.startsWith("|")) continue;
80997
+ if (/\|\s*Model\s/i.test(trimmed)) {
80998
+ columnIndices = parseHeaderColumns(trimmed);
80999
+ continue;
81000
+ }
81001
+ if (/^[\s|:-]+$/.test(trimmed) || !columnIndices) continue;
81002
+ const entry = parseDataRow(trimmed, columnIndices);
81003
+ if (entry && !seenModels.has(entry.modelName.toLowerCase())) {
81004
+ seenModels.add(entry.modelName.toLowerCase());
81005
+ results.push(entry);
81006
+ }
81007
+ }
81008
+ return results;
81009
+ }
81010
+ function parseDataRow(line, columnIndices) {
81011
+ const cells = splitMarkdownRow(line);
81012
+ if (cells.length <= columnIndices.output) return null;
81013
+ const modelName = cells[columnIndices.model].trim();
81014
+ const inputPrice = parseDollarValue(cells[columnIndices.input]);
81015
+ const cachedPrice = columnIndices.cached >= 0 ? parseDollarValue(cells[columnIndices.cached]) : null;
81016
+ const outputPrice = parseDollarValue(cells[columnIndices.output]);
81017
+ if (!modelName || inputPrice === null || outputPrice === null) return null;
81018
+ return {
81019
+ modelName,
81020
+ inputMultiplier: inputPrice * PRICE_TO_MULTIPLIER,
81021
+ cachedInputMultiplier: cachedPrice !== null ? cachedPrice * PRICE_TO_MULTIPLIER : null,
81022
+ outputMultiplier: outputPrice * PRICE_TO_MULTIPLIER
81023
+ };
81024
+ }
81025
+ function parseHeaderColumns(headerLine) {
81026
+ const cells = splitMarkdownRow(headerLine).map((c) => c.trim().toLowerCase());
81027
+ const model = cells.findIndex((c) => c === "model" || c === "model name");
81028
+ const input = cells.findIndex(
81029
+ (c) => (c === "input" || c === "input multiplier") && !c.includes("cached")
81030
+ );
81031
+ const cached2 = cells.findIndex(
81032
+ (c) => c.includes("cached input") || c === "cached input multiplier"
81033
+ );
81034
+ const output = cells.findIndex(
81035
+ (c) => (c === "output" || c === "output multiplier") && !c.includes("cached")
81036
+ );
81037
+ if (model < 0 || input < 0 || output < 0) {
81038
+ return null;
81039
+ }
81040
+ return { model, input, cached: cached2 >= 0 ? cached2 : -1, output };
81041
+ }
81042
+ function splitMarkdownRow(line) {
81043
+ const parts = line.split("|");
81044
+ if (parts[0].trim() === "") parts.shift();
81045
+ if (parts[parts.length - 1]?.trim() === "") parts.pop();
81046
+ return parts;
81047
+ }
81048
+ function parseDollarValue(cell) {
81049
+ if (!cell) return null;
81050
+ const cleaned = cell.trim().replace(/[$,]/g, "");
81051
+ if (cleaned.toLowerCase() === "n/a" || cleaned === "" || cleaned === "-") {
81052
+ return null;
81053
+ }
81054
+ const value = Number.parseFloat(cleaned);
81055
+ return Number.isNaN(value) ? null : value;
81056
+ }
81057
+
81058
+ // packages/daemon/src/models/types.ts
81059
+ var TIER_RANGES = {
81060
+ trivial: { min: 0, max: 0.33 },
81061
+ fast: { min: 0.34, max: 1 },
81062
+ standard: { min: 1.1, max: 5 },
81063
+ premium: { min: 5.1, max: 15 },
81064
+ ultra: { min: 15.1, max: Number.POSITIVE_INFINITY }
81065
+ };
81066
+ function computeTierFromMultiplier(premiumMultiplier) {
81067
+ if (premiumMultiplier === null) {
81068
+ return "standard";
81069
+ }
81070
+ for (const [tier, range] of Object.entries(TIER_RANGES)) {
81071
+ if (premiumMultiplier >= range.min && premiumMultiplier <= range.max) {
81072
+ return tier;
81073
+ }
81074
+ }
81075
+ return "ultra";
81076
+ }
81077
+ var TOKEN_UNIT_PRICE = 1e-5;
81078
+
81079
+ // packages/daemon/src/models/registry.ts
81080
+ function stripVendorPrefix(id) {
81081
+ const slashIndex = id.indexOf("/");
81082
+ return slashIndex >= 0 ? id.slice(slashIndex + 1) : id;
81083
+ }
81084
+ function normalizeModelName(name) {
81085
+ return stripVendorPrefix(name).toLowerCase().replace(/^openai\s+/i, "").replace(/\s+/g, "-").replace(/[^a-z0-9.\-]/g, "").trim();
81086
+ }
81087
+ async function fetchCatalogIntoMap(modelMap, result, logger2) {
81088
+ try {
81089
+ const catalogModels = await fetchModelCatalog();
81090
+ result.catalogFetched = true;
81091
+ for (const m of catalogModels) {
81092
+ const key = normalizeModelName(m.id);
81093
+ const id = stripVendorPrefix(m.id);
81094
+ modelMap.set(key, { id, displayName: m.displayName, available: true });
81095
+ }
81096
+ } catch (error51) {
81097
+ const msg = error51 instanceof Error ? error51.message : String(error51);
81098
+ result.errors.push(`Catalog fetch failed: ${msg}`);
81099
+ logger2?.warn(`Model catalog fetch failed: ${msg}`);
81100
+ }
81101
+ }
81102
+ async function scrapeTokenPricingIntoMap(modelMap, result, logger2) {
81103
+ try {
81104
+ const tokenPricing = await scrapeTokenUnitPricing();
81105
+ result.tokenPricingScraped = true;
81106
+ for (const tp of tokenPricing) {
81107
+ const key = normalizeModelName(tp.modelName);
81108
+ const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
81109
+ if (existing) {
81110
+ existing.tokenInputMultiplier = tp.inputMultiplier;
81111
+ existing.tokenOutputMultiplier = tp.outputMultiplier;
81112
+ existing.cachedInputMultiplier = tp.cachedInputMultiplier;
81113
+ } else {
81114
+ modelMap.set(key, {
81115
+ id: key,
81116
+ displayName: tp.modelName,
81117
+ tokenInputMultiplier: tp.inputMultiplier,
81118
+ tokenOutputMultiplier: tp.outputMultiplier,
81119
+ cachedInputMultiplier: tp.cachedInputMultiplier,
81120
+ available: true
81121
+ });
81122
+ }
81123
+ }
81124
+ } catch (error51) {
81125
+ const msg = error51 instanceof Error ? error51.message : String(error51);
81126
+ result.errors.push(`Token pricing scrape failed: ${msg}`);
81127
+ logger2?.warn(`Token pricing scrape failed: ${msg}`);
81128
+ }
81129
+ }
81130
+ async function scrapePremiumPricingIntoMap(modelMap, result, logger2) {
81131
+ try {
81132
+ const premiumPricing = await scrapePremiumRequestPricing();
81133
+ result.premiumPricingScraped = true;
81134
+ for (const pp of premiumPricing) {
81135
+ const key = normalizeModelName(pp.modelName);
81136
+ const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
81137
+ if (existing) {
81138
+ existing.premiumMultiplier = pp.multiplier;
81139
+ } else {
81140
+ modelMap.set(key, {
81141
+ id: key,
81142
+ displayName: pp.modelName,
81143
+ premiumMultiplier: pp.multiplier,
81144
+ available: true
81145
+ });
81146
+ }
81147
+ }
81148
+ } catch (error51) {
81149
+ const msg = error51 instanceof Error ? error51.message : String(error51);
81150
+ result.errors.push(`Premium pricing scrape failed: ${msg}`);
81151
+ logger2?.warn(`Premium pricing scrape failed: ${msg}`);
81152
+ }
81153
+ }
81154
+ async function scrapeCopilotPricingIntoMap(modelMap, result, logger2) {
81155
+ try {
81156
+ const copilotPricing = await scrapeCopilotPricing();
81157
+ result.copilotPricingScraped = true;
81158
+ for (const cp of copilotPricing) {
81159
+ const key = normalizeModelName(cp.modelName);
81160
+ const existing = modelMap.get(key) ?? findClosestKey(modelMap, key);
81161
+ if (existing) {
81162
+ existing.tokenInputMultiplier = cp.inputMultiplier;
81163
+ existing.tokenOutputMultiplier = cp.outputMultiplier;
81164
+ if (cp.cachedInputMultiplier !== null) {
81165
+ existing.cachedInputMultiplier = cp.cachedInputMultiplier;
81166
+ }
81167
+ } else {
81168
+ modelMap.set(key, {
81169
+ id: key,
81170
+ displayName: cp.modelName,
81171
+ tokenInputMultiplier: cp.inputMultiplier,
81172
+ tokenOutputMultiplier: cp.outputMultiplier,
81173
+ cachedInputMultiplier: cp.cachedInputMultiplier,
81174
+ available: true
81175
+ });
81176
+ }
81177
+ }
81178
+ } catch (error51) {
81179
+ const msg = error51 instanceof Error ? error51.message : String(error51);
81180
+ result.errors.push(`Copilot pricing scrape failed: ${msg}`);
81181
+ logger2?.warn(`Copilot pricing scrape failed: ${msg}`);
81182
+ }
81183
+ }
81184
+ async function refreshModelPricing(logger2) {
81185
+ const result = {
81186
+ modelsUpdated: 0,
81187
+ catalogFetched: false,
81188
+ tokenPricingScraped: false,
81189
+ premiumPricingScraped: false,
81190
+ copilotPricingScraped: false,
81191
+ errors: []
81192
+ };
81193
+ const modelMap = /* @__PURE__ */ new Map();
81194
+ await fetchCatalogIntoMap(modelMap, result, logger2);
81195
+ await scrapeTokenPricingIntoMap(modelMap, result, logger2);
81196
+ await scrapeCopilotPricingIntoMap(modelMap, result, logger2);
81197
+ await scrapePremiumPricingIntoMap(modelMap, result, logger2);
81198
+ if (!result.catalogFetched && !result.tokenPricingScraped && !result.premiumPricingScraped && !result.copilotPricingScraped) {
81199
+ logger2?.warn("All pricing sources failed, no models available");
81200
+ return result;
81201
+ }
81202
+ const db = await getDatabase();
81203
+ const now = nowIso();
81204
+ await db.execute("DELETE FROM model_pricing WHERE id LIKE '%/%'");
81205
+ for (const model of modelMap.values()) {
81206
+ if (model.tokenInputMultiplier == null) {
81207
+ continue;
81208
+ }
81209
+ const tier = computeTierFromMultiplier(model.premiumMultiplier ?? null);
81210
+ await upsertModel(db, {
81211
+ id: model.id,
81212
+ displayName: model.displayName,
81213
+ premiumMultiplier: model.premiumMultiplier ?? null,
81214
+ tokenInputMultiplier: model.tokenInputMultiplier,
81215
+ tokenOutputMultiplier: model.tokenOutputMultiplier ?? null,
81216
+ cachedInputMultiplier: model.cachedInputMultiplier ?? null,
81217
+ tier,
81218
+ available: model.available ?? true,
81219
+ updatedAt: now
81220
+ });
81221
+ result.modelsUpdated++;
81222
+ }
81223
+ return result;
81224
+ }
81225
+ async function getModelsForTier(tier) {
81226
+ const db = await getDatabase();
81227
+ const result = await db.execute({
81228
+ sql: "SELECT * FROM model_pricing WHERE tier = ? AND available = 1 ORDER BY premium_multiplier ASC NULLS LAST",
81229
+ args: [tier]
81230
+ });
81231
+ return result.rows.map(rowToModelPricing);
81232
+ }
81233
+ async function getCheapestInTier(tier) {
81234
+ const models = await getModelsForTier(tier);
81235
+ return models[0] ?? null;
81236
+ }
81237
+ async function getModelPricing(modelId) {
81238
+ const db = await getDatabase();
81239
+ const result = await db.execute({
81240
+ sql: "SELECT * FROM model_pricing WHERE id = ?",
81241
+ args: [modelId]
81242
+ });
81243
+ if (result.rows.length > 0) {
81244
+ return rowToModelPricing(result.rows[0]);
81245
+ }
81246
+ const allModels = await db.execute(
81247
+ "SELECT * FROM model_pricing WHERE token_input_multiplier IS NOT NULL ORDER BY length(id) DESC"
81248
+ );
81249
+ for (const row of allModels.rows) {
81250
+ const storedId = asString(row.id);
81251
+ if (modelId.startsWith(storedId) || storedId.startsWith(modelId)) {
81252
+ return rowToModelPricing(row);
81253
+ }
81254
+ }
81255
+ return null;
81256
+ }
81257
+ async function getCheapestAvailableModel() {
81258
+ const tiers = ["trivial", "fast", "standard", "premium", "ultra"];
81259
+ for (const tier of tiers) {
81260
+ const model = await getCheapestInTier(tier);
81261
+ if (model) {
81262
+ return model;
81263
+ }
81264
+ }
81265
+ return null;
81266
+ }
81267
+ function calculateTokenUnitCost(inputTokens, outputTokens, inputMultiplier, outputMultiplier) {
81268
+ if (inputMultiplier === null || outputMultiplier === null) {
81269
+ return 0;
81270
+ }
81271
+ const tokenUnits = inputTokens * inputMultiplier + outputTokens * outputMultiplier;
81272
+ return tokenUnits * TOKEN_UNIT_PRICE;
81273
+ }
81274
+ function getNextTierUp(tier) {
81275
+ const order = ["trivial", "fast", "standard", "premium", "ultra"];
81276
+ const idx = order.indexOf(tier);
81277
+ if (idx < 0 || idx >= order.length - 1) {
81278
+ return null;
81279
+ }
81280
+ return order[idx + 1];
81281
+ }
81282
+ async function upsertModel(db, model) {
81283
+ await db.execute({
81284
+ sql: `INSERT INTO model_pricing (id, display_name, premium_multiplier, token_input_multiplier, token_output_multiplier, cached_input_multiplier, tier, available, updated_at)
81285
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
81286
+ ON CONFLICT(id) DO UPDATE SET
81287
+ display_name = excluded.display_name,
81288
+ premium_multiplier = COALESCE(excluded.premium_multiplier, model_pricing.premium_multiplier),
81289
+ token_input_multiplier = COALESCE(excluded.token_input_multiplier, model_pricing.token_input_multiplier),
81290
+ token_output_multiplier = COALESCE(excluded.token_output_multiplier, model_pricing.token_output_multiplier),
81291
+ cached_input_multiplier = COALESCE(excluded.cached_input_multiplier, model_pricing.cached_input_multiplier),
81292
+ tier = excluded.tier,
81293
+ available = excluded.available,
81294
+ updated_at = excluded.updated_at`,
81295
+ args: [
81296
+ model.id,
81297
+ model.displayName,
81298
+ model.premiumMultiplier,
81299
+ model.tokenInputMultiplier,
81300
+ model.tokenOutputMultiplier,
81301
+ model.cachedInputMultiplier,
81302
+ model.tier,
81303
+ model.available ? 1 : 0,
81304
+ model.updatedAt
81305
+ ]
81306
+ });
81307
+ }
81308
+ function rowToModelPricing(row) {
81309
+ return {
81310
+ id: stripVendorPrefix(asString(row.id)),
81311
+ displayName: asString(row.display_name),
81312
+ premiumMultiplier: asNullableNumber(row.premium_multiplier),
81313
+ tokenInputMultiplier: asNullableNumber(row.token_input_multiplier),
81314
+ tokenOutputMultiplier: asNullableNumber(row.token_output_multiplier),
81315
+ cachedInputMultiplier: asNullableNumber(row.cached_input_multiplier),
81316
+ tier: asString(row.tier),
81317
+ available: asNumber(row.available) === 1,
81318
+ updatedAt: asString(row.updated_at)
81319
+ };
81320
+ }
81321
+ function findClosestKey(map2, targetKey) {
81322
+ for (const [key, value] of map2) {
81323
+ if (key.includes(targetKey) || targetKey.includes(key)) {
81324
+ return value;
81325
+ }
81326
+ }
81327
+ return void 0;
81328
+ }
81379
81329
 
81380
81330
  // packages/daemon/src/orchestrator/system-prompt.ts
81381
81331
  function formatSquadRoster(squads) {
@@ -81709,9 +81659,6 @@ async function sendMessage(session, message2, onChunk) {
81709
81659
  return operation;
81710
81660
  }
81711
81661
 
81712
- // packages/daemon/src/orchestrator/orchestrator.ts
81713
- init_registry();
81714
-
81715
81662
  // packages/daemon/src/skills/loader.ts
81716
81663
  var import_gray_matter2 = __toESM(require_gray_matter(), 1);
81717
81664
  init_paths();
@@ -82063,7 +82010,6 @@ var executeCodingToolCall = async (toolName, rawArgs) => {
82063
82010
  // packages/daemon/src/orchestrator/tools/inbox.ts
82064
82011
  init_dist();
82065
82012
  init_zod();
82066
- init_db();
82067
82013
  var inboxReplySchema = external_exports.object({
82068
82014
  itemId: external_exports.string().trim().min(1),
82069
82015
  reply: external_exports.string().trim().min(1)
@@ -82335,42 +82281,39 @@ async function isSquadAvailable(squadId) {
82335
82281
  }
82336
82282
 
82337
82283
  // packages/daemon/src/execution/agent.ts
82338
- init_registry();
82339
82284
  import { exec as exec3 } from "node:child_process";
82340
82285
  import { mkdir as mkdir9, readFile as readFile7, readdir as readdir5, stat as stat3, writeFile as writeFile6 } from "node:fs/promises";
82341
82286
  import { dirname as dirname8, extname as extname3, isAbsolute, join as join11, relative as relative3, resolve as resolve4 } from "node:path";
82342
82287
  import { promisify as promisify3 } from "node:util";
82343
82288
  import {
82344
- CopilotClient as CopilotClient3,
82345
- approveAll as approveAll3,
82289
+ CopilotClient as CopilotClient2,
82290
+ approveAll as approveAll2,
82346
82291
  defineTool
82347
82292
  } from "@github/copilot-sdk";
82348
82293
 
82349
82294
  // packages/daemon/src/squad/model-selector.ts
82350
- init_registry();
82351
- import { CopilotClient as CopilotClient2, approveAll as approveAll2 } from "@github/copilot-sdk";
82352
- var VALID_TIERS = ["trivial", "fast", "standard", "premium", "ultra"];
82353
- var CLASSIFICATION_PROMPT = `You are a task complexity classifier. Given a task description, classify its complexity into exactly one tier.
82354
-
82355
- Tiers (from simplest to most complex):
82356
- - trivial: Typos, renames, comment changes, config tweaks, formatting
82357
- - fast: Simple bug fixes, small features, documentation updates, single-file changes
82358
- - standard: Feature implementation, multi-file changes, moderate refactoring
82359
- - premium: Architecture changes, complex refactoring, security work, performance optimization
82360
- - ultra: System-wide redesigns, critical infrastructure, cross-cutting concerns
82361
-
82362
- Reply with ONLY the tier name (one word, lowercase). Nothing else.`;
82295
+ var TIER_KEYWORDS = {
82296
+ ultra: [/system[- ]wide/i, /redesign/i, /infrastructure/i, /cross[- ]cutting/i, /migration/i],
82297
+ premium: [/architect/i, /security/i, /performance/i, /complex refactor/i, /optimization/i],
82298
+ standard: [/implement/i, /feature/i, /multi[- ]file/i, /refactor/i, /integration/i],
82299
+ fast: [/fix/i, /bug/i, /update/i, /documentation/i, /single[- ]file/i, /small/i],
82300
+ trivial: [/typo/i, /rename/i, /comment/i, /config/i, /format/i]
82301
+ };
82302
+ function classifyTaskComplexity(taskDescription) {
82303
+ const tiers = ["ultra", "premium", "standard", "fast", "trivial"];
82304
+ for (const tier of tiers) {
82305
+ if (TIER_KEYWORDS[tier].some((pattern) => pattern.test(taskDescription))) {
82306
+ return tier;
82307
+ }
82308
+ }
82309
+ return "standard";
82310
+ }
82363
82311
  async function selectModelForTask(taskDescription) {
82364
82312
  const classifierModel = await getCheapestAvailableModel();
82365
82313
  if (!classifierModel) {
82366
82314
  throw new Error("No models available in pricing database");
82367
82315
  }
82368
- let tier;
82369
- try {
82370
- tier = await classifyTaskComplexity(taskDescription, classifierModel.id);
82371
- } catch {
82372
- return classifierModel.id;
82373
- }
82316
+ const tier = classifyTaskComplexity(taskDescription);
82374
82317
  const selectedModel = await getCheapestInTier(tier);
82375
82318
  if (selectedModel) {
82376
82319
  return selectedModel.id;
@@ -82384,30 +82327,6 @@ async function selectModelForTask(taskDescription) {
82384
82327
  }
82385
82328
  return classifierModel.id;
82386
82329
  }
82387
- async function classifyTaskComplexity(taskDescription, modelId) {
82388
- let client2 = null;
82389
- try {
82390
- client2 = new CopilotClient2();
82391
- await client2.start();
82392
- const session = await client2.createSession({
82393
- model: modelId,
82394
- onPermissionRequest: approveAll2,
82395
- systemMessage: { content: CLASSIFICATION_PROMPT }
82396
- });
82397
- try {
82398
- const response = await session.sendAndWait({ prompt: `Task: ${taskDescription}` }, 15e3);
82399
- const raw = (response.text ?? "").trim().toLowerCase();
82400
- const tier = VALID_TIERS.find((t) => raw.includes(t));
82401
- return tier ?? "standard";
82402
- } finally {
82403
- await session.disconnect().catch(() => void 0);
82404
- }
82405
- } finally {
82406
- if (client2) {
82407
- await client2.stop().catch(() => void 0);
82408
- }
82409
- }
82410
- }
82411
82330
 
82412
82331
  // packages/daemon/src/execution/history.ts
82413
82332
  var DEFAULT_CONTEXT_LIMIT = 5;
@@ -82438,6 +82357,7 @@ var execAsync3 = promisify3(exec3);
82438
82357
  var MAX_FILE_SIZE = 2e5;
82439
82358
  var MAX_LIST_RESULTS = 200;
82440
82359
  var MAX_SEARCH_RESULTS = 100;
82360
+ var SESSION_CREATE_TIMEOUT_MS = 3e4;
82441
82361
  function createEmptyUsage() {
82442
82362
  return {
82443
82363
  inputTokens: 0,
@@ -82694,15 +82614,15 @@ async function executeAgentTask(member, task, worktreePath, options2) {
82694
82614
  const mcpServerNote = options2?.mcpServers?.length ? `Available MCP server labels: ${options2.mcpServers.join(", ")}.` : "No additional MCP servers were configured for this run.";
82695
82615
  let client2 = null;
82696
82616
  try {
82697
- client2 = new CopilotClient3({ workingDirectory: worktreePath });
82617
+ client2 = new CopilotClient2({ workingDirectory: worktreePath });
82698
82618
  await client2.start();
82699
82619
  const model = member.model ? stripVendorPrefix(member.model) : await selectModelForTask(task.description);
82700
- const session = await client2.createSession({
82620
+ const sessionPromise = client2.createSession({
82701
82621
  model,
82702
82622
  workingDirectory: worktreePath,
82703
82623
  tools,
82704
82624
  availableTools: ["custom:*"],
82705
- onPermissionRequest: approveAll3,
82625
+ onPermissionRequest: approveAll2,
82706
82626
  systemMessage: {
82707
82627
  content: `${member.systemPrompt}
82708
82628
 
@@ -82712,6 +82632,15 @@ ${historyContext}
82712
82632
  ${mcpServerNote}${options2?.instancePromptSuffix ?? ""}`
82713
82633
  }
82714
82634
  });
82635
+ const session = await Promise.race([
82636
+ sessionPromise,
82637
+ new Promise(
82638
+ (_, reject) => setTimeout(
82639
+ () => reject(new Error(`Session creation timed out after ${SESSION_CREATE_TIMEOUT_MS}ms`)),
82640
+ SESSION_CREATE_TIMEOUT_MS
82641
+ )
82642
+ )
82643
+ ]);
82715
82644
  session.on("assistant.usage", (event) => {
82716
82645
  usageEvents.push(event.data);
82717
82646
  mergeUsage(usage, event.data);
@@ -82783,7 +82712,7 @@ import { exec as exec4 } from "node:child_process";
82783
82712
  import { access, readFile as readFile8 } from "node:fs/promises";
82784
82713
  import { join as join12 } from "node:path";
82785
82714
  import { promisify as promisify4 } from "node:util";
82786
- import { CopilotClient as CopilotClient4, approveAll as approveAll4 } from "@github/copilot-sdk";
82715
+ import { CopilotClient as CopilotClient3, approveAll as approveAll3 } from "@github/copilot-sdk";
82787
82716
 
82788
82717
  // packages/daemon/src/squad/roles.ts
82789
82718
  var ROLE_GUIDELINES = [
@@ -82926,13 +82855,13 @@ Return strict JSON in this shape:
82926
82855
  }`;
82927
82856
  let client2 = null;
82928
82857
  try {
82929
- client2 = new CopilotClient4({ workingDirectory: repoPath });
82858
+ client2 = new CopilotClient3({ workingDirectory: repoPath });
82930
82859
  await client2.start();
82931
82860
  const model = await selectModelForTask(`Create implementation plan: ${objective.description}`);
82932
82861
  const session = await client2.createSession({
82933
82862
  model,
82934
82863
  workingDirectory: repoPath,
82935
- onPermissionRequest: approveAll4,
82864
+ onPermissionRequest: approveAll3,
82936
82865
  systemMessage: {
82937
82866
  content: `${TEAM_LEAD_PROMPT}
82938
82867
 
@@ -83035,8 +82964,7 @@ async function createPullRequest(options2) {
83035
82964
  init_dist();
83036
82965
  import { exec as exec6 } from "node:child_process";
83037
82966
  import { promisify as promisify6 } from "node:util";
83038
- import { CopilotClient as CopilotClient5, approveAll as approveAll5 } from "@github/copilot-sdk";
83039
- init_registry();
82967
+ import { CopilotClient as CopilotClient4, approveAll as approveAll4 } from "@github/copilot-sdk";
83040
82968
  var execAsync6 = promisify6(exec6);
83041
82969
  var GIT_DIFF_MAX_BUFFER = 10 * 1024 * 1024;
83042
82970
  function extractJsonObject2(content) {
@@ -83076,13 +83004,13 @@ Return strict JSON:
83076
83004
  }`;
83077
83005
  let client2 = null;
83078
83006
  try {
83079
- client2 = new CopilotClient5({ workingDirectory: worktreePath });
83007
+ client2 = new CopilotClient4({ workingDirectory: worktreePath });
83080
83008
  await client2.start();
83081
83009
  const model = qaMember.model ? stripVendorPrefix(qaMember.model) : await selectModelForTask(`QA review: ${objective.description}`);
83082
83010
  const session = await client2.createSession({
83083
83011
  model,
83084
83012
  workingDirectory: worktreePath,
83085
- onPermissionRequest: approveAll5,
83013
+ onPermissionRequest: approveAll4,
83086
83014
  systemMessage: {
83087
83015
  content: QA_PROMPT
83088
83016
  }
@@ -83152,8 +83080,7 @@ async function handleQARejection(objectiveId, feedback) {
83152
83080
  }
83153
83081
 
83154
83082
  // packages/daemon/src/execution/review.ts
83155
- init_registry();
83156
- import { CopilotClient as CopilotClient6, approveAll as approveAll6 } from "@github/copilot-sdk";
83083
+ import { CopilotClient as CopilotClient5, approveAll as approveAll5 } from "@github/copilot-sdk";
83157
83084
  function extractJsonObject3(content) {
83158
83085
  const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/i);
83159
83086
  if (fenced?.[1]) {
@@ -83198,12 +83125,12 @@ Return strict JSON:
83198
83125
  }`;
83199
83126
  let client2 = null;
83200
83127
  try {
83201
- client2 = new CopilotClient6();
83128
+ client2 = new CopilotClient5();
83202
83129
  await client2.start();
83203
83130
  const model = teamLead.model ? stripVendorPrefix(teamLead.model) : await selectModelForTask(`Code review: ${objective.description}`);
83204
83131
  const session = await client2.createSession({
83205
83132
  model,
83206
- onPermissionRequest: approveAll6,
83133
+ onPermissionRequest: approveAll5,
83207
83134
  systemMessage: {
83208
83135
  content: `${TEAM_LEAD_PROMPT}
83209
83136
 
@@ -83348,60 +83275,49 @@ async function executePendingTasks(objective, members, worktreePath, mcpServers,
83348
83275
  if (pendingTasks.length === 0) {
83349
83276
  return getTasksForObjective(objective.id);
83350
83277
  }
83351
- const results = await Promise.allSettled(
83352
- pendingTasks.map(async (task) => {
83353
- const member = members.find((candidate) => candidate.id === task.assigneeId);
83354
- if (!member) {
83355
- const failedTask = await markTaskFailed(
83356
- task.id,
83357
- "No squad member matched the task assignee."
83358
- );
83359
- eventBus.emit(EVENT_NAMES.TASK_FAILED, {
83360
- task: failedTask,
83361
- agentName: "unassigned",
83362
- reason: failedTask.result ?? "No assignee"
83363
- });
83364
- throw new Error(`Task ${task.id} has no matching assignee`);
83365
- }
83366
- const inProgressTask = await updateTaskStatus(
83278
+ for (const task of pendingTasks) {
83279
+ const member = members.find((candidate) => candidate.id === task.assigneeId);
83280
+ if (!member) {
83281
+ const failedTask = await markTaskFailed(
83367
83282
  task.id,
83368
- "in_progress",
83369
- task.result ?? void 0
83283
+ "No squad member matched the task assignee."
83370
83284
  );
83371
- const startedTask = inProgressTask ?? task;
83372
- eventBus.emit(EVENT_NAMES.TASK_STARTED, { task: startedTask, agentName: member.name });
83373
- eventBus.emit(EVENT_NAMES.AGENT_EXECUTING, {
83374
- squadId: objective.squadId,
83375
- agentId: member.id,
83376
- taskId: task.id
83377
- });
83378
- const execution = await executeAgentTask(member, task, worktreePath, {
83379
- mcpServers,
83380
- instancePromptSuffix
83285
+ eventBus.emit(EVENT_NAMES.TASK_FAILED, {
83286
+ task: failedTask,
83287
+ agentName: "unassigned",
83288
+ reason: failedTask.result ?? "No assignee"
83381
83289
  });
83382
- if (!execution.success) {
83383
- const failedTask = await markTaskFailed(task.id, execution.result);
83384
- eventBus.emit(EVENT_NAMES.TASK_FAILED, {
83385
- task: failedTask,
83386
- agentName: member.name,
83387
- reason: execution.result
83388
- });
83389
- throw new Error(execution.result);
83390
- }
83391
- const completedTask = await markTaskComplete(task.id, execution.result);
83392
- await extractLearnings(member.id, member.squadId, execution.result);
83393
- eventBus.emit(EVENT_NAMES.TASK_COMPLETED, { task: completedTask, agentName: member.name });
83394
- eventBus.emit(EVENT_NAMES.AGENT_COMPLETED, {
83395
- squadId: objective.squadId,
83396
- agentId: member.id,
83397
- taskId: task.id
83290
+ throw new Error(`Task ${task.id} has no matching assignee`);
83291
+ }
83292
+ const inProgressTask = await updateTaskStatus(task.id, "in_progress", task.result ?? void 0);
83293
+ const startedTask = inProgressTask ?? task;
83294
+ eventBus.emit(EVENT_NAMES.TASK_STARTED, { task: startedTask, agentName: member.name });
83295
+ eventBus.emit(EVENT_NAMES.AGENT_EXECUTING, {
83296
+ squadId: objective.squadId,
83297
+ agentId: member.id,
83298
+ taskId: task.id
83299
+ });
83300
+ const execution = await executeAgentTask(member, task, worktreePath, {
83301
+ mcpServers,
83302
+ instancePromptSuffix
83303
+ });
83304
+ if (!execution.success) {
83305
+ const failedTask = await markTaskFailed(task.id, execution.result);
83306
+ eventBus.emit(EVENT_NAMES.TASK_FAILED, {
83307
+ task: failedTask,
83308
+ agentName: member.name,
83309
+ reason: execution.result
83398
83310
  });
83399
- return completedTask;
83400
- })
83401
- );
83402
- const failed = results.find((result) => result.status === "rejected");
83403
- if (failed && failed.status === "rejected") {
83404
- throw failed.reason instanceof Error ? failed.reason : new Error(String(failed.reason));
83311
+ throw new Error(execution.result);
83312
+ }
83313
+ const completedTask = await markTaskComplete(task.id, execution.result);
83314
+ await extractLearnings(member.id, member.squadId, execution.result);
83315
+ eventBus.emit(EVENT_NAMES.TASK_COMPLETED, { task: completedTask, agentName: member.name });
83316
+ eventBus.emit(EVENT_NAMES.AGENT_COMPLETED, {
83317
+ squadId: objective.squadId,
83318
+ agentId: member.id,
83319
+ taskId: task.id
83320
+ });
83405
83321
  }
83406
83322
  return getTasksForObjective(objective.id);
83407
83323
  }
@@ -84594,7 +84510,6 @@ function createOrchestrator(config2, eventBus2) {
84594
84510
  // packages/daemon/src/scheduler/engine.ts
84595
84511
  init_dist();
84596
84512
  var import_cron_parser2 = __toESM(require_dist(), 1);
84597
- init_db();
84598
84513
  var Scheduler = class {
84599
84514
  orchestrator;
84600
84515
  eventBus;
@@ -84682,9 +84597,6 @@ function createScheduler(orchestrator2, eventBus2) {
84682
84597
  return new Scheduler(orchestrator2, eventBus2);
84683
84598
  }
84684
84599
 
84685
- // packages/daemon/src/index.ts
84686
- init_db();
84687
-
84688
84600
  // packages/daemon/src/telegram/bot.ts
84689
84601
  var import_grammy = __toESM(require_mod2(), 1);
84690
84602
  var TelegramBot = class {