heyio 4.2.5 → 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.
@@ -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.2.5";
82
+ APP_VERSION = "4.2.7";
83
83
  API_PORT = 7777;
84
84
  API_HOST = "0.0.0.0";
85
85
  DEFAULT_MODEL = "gpt-4o";
@@ -77130,6 +77130,11 @@ var MIGRATIONS = [
77130
77130
  agent_name = (SELECT sm.name FROM squad_members sm WHERE sm.id = token_usage.agent_id)
77131
77131
  WHERE squad_id IS NOT NULL OR agent_id IS NOT NULL`
77132
77132
  ]
77133
+ },
77134
+ {
77135
+ version: 5,
77136
+ name: "add-squad-soft-delete",
77137
+ statements: ["ALTER TABLE squads ADD COLUMN deleted_at TEXT"]
77133
77138
  }
77134
77139
  ];
77135
77140
  var client = null;
@@ -77277,7 +77282,8 @@ async function createSquad(data, db) {
77277
77282
  status: data.status ?? "active",
77278
77283
  config: data.config,
77279
77284
  createdAt: timestamp,
77280
- updatedAt: timestamp
77285
+ updatedAt: timestamp,
77286
+ deletedAt: null
77281
77287
  };
77282
77288
  await database.execute({
77283
77289
  sql: `INSERT INTO squads (id, name, repo_url, repo_owner, repo_name, status, config, created_at, updated_at)
@@ -77299,7 +77305,7 @@ async function createSquad(data, db) {
77299
77305
  async function getSquad(id, db) {
77300
77306
  const database = db ?? await getDatabase();
77301
77307
  const squadResult = await database.execute({
77302
- sql: "SELECT * FROM squads WHERE id = ? LIMIT 1",
77308
+ sql: "SELECT * FROM squads WHERE id = ? AND deleted_at IS NULL LIMIT 1",
77303
77309
  args: [id]
77304
77310
  });
77305
77311
  const row = squadResult.rows[0];
@@ -77315,7 +77321,7 @@ async function getSquad(id, db) {
77315
77321
  async function getSquadByName(name, db) {
77316
77322
  const database = db ?? await getDatabase();
77317
77323
  const result = await database.execute({
77318
- sql: "SELECT * FROM squads WHERE name = ? LIMIT 1",
77324
+ sql: "SELECT * FROM squads WHERE name = ? AND deleted_at IS NULL LIMIT 1",
77319
77325
  args: [name]
77320
77326
  });
77321
77327
  const row = result.rows[0];
@@ -77328,7 +77334,9 @@ async function getSquadByName(name, db) {
77328
77334
  }
77329
77335
  async function listSquads(db) {
77330
77336
  const database = db ?? await getDatabase();
77331
- const result = await database.execute("SELECT * FROM squads ORDER BY created_at DESC, id DESC");
77337
+ const result = await database.execute(
77338
+ "SELECT * FROM squads WHERE deleted_at IS NULL ORDER BY created_at DESC, id DESC"
77339
+ );
77332
77340
  return result.rows.map((row) => mapSquad(row));
77333
77341
  }
77334
77342
  async function updateSquad(id, data, db) {
@@ -77347,7 +77355,8 @@ async function updateSquad(id, data, db) {
77347
77355
  status: data.status ?? existing.status,
77348
77356
  config: data.config ?? existing.config,
77349
77357
  createdAt: existing.createdAt,
77350
- updatedAt
77358
+ updatedAt,
77359
+ deletedAt: existing.deletedAt
77351
77360
  };
77352
77361
  await database.execute({
77353
77362
  sql: `UPDATE squads
@@ -77368,16 +77377,34 @@ async function updateSquad(id, data, db) {
77368
77377
  }
77369
77378
  async function deleteSquad(id, db) {
77370
77379
  const database = db ?? await getDatabase();
77380
+ const now = nowIso();
77371
77381
  const result = await database.execute({
77372
- sql: "DELETE FROM squads WHERE id = ?",
77373
- args: [id]
77382
+ sql: "UPDATE squads SET status = 'deleted', deleted_at = ?, updated_at = ? WHERE id = ? AND deleted_at IS NULL",
77383
+ args: [now, now, id]
77374
77384
  });
77375
77385
  return result.rowsAffected > 0;
77376
77386
  }
77387
+ async function restoreSquad(id, db) {
77388
+ const database = db ?? await getDatabase();
77389
+ const now = nowIso();
77390
+ const result = await database.execute({
77391
+ sql: "UPDATE squads SET status = 'active', deleted_at = NULL, updated_at = ? WHERE id = ? AND deleted_at IS NOT NULL",
77392
+ args: [now, id]
77393
+ });
77394
+ if (result.rowsAffected === 0) return null;
77395
+ return getSquadRow(id, database);
77396
+ }
77397
+ async function listDeletedSquads(db) {
77398
+ const database = db ?? await getDatabase();
77399
+ const result = await database.execute(
77400
+ "SELECT * FROM squads WHERE deleted_at IS NOT NULL ORDER BY deleted_at DESC, id DESC"
77401
+ );
77402
+ return result.rows.map((row) => mapSquad(row));
77403
+ }
77377
77404
  async function getSquadByRepo(repoOwner, repoName, db) {
77378
77405
  const database = db ?? await getDatabase();
77379
77406
  const result = await database.execute({
77380
- sql: "SELECT * FROM squads WHERE repo_owner = ? AND repo_name = ? LIMIT 1",
77407
+ sql: "SELECT * FROM squads WHERE repo_owner = ? AND repo_name = ? AND deleted_at IS NULL LIMIT 1",
77381
77408
  args: [repoOwner, repoName]
77382
77409
  });
77383
77410
  const row = result.rows[0];
@@ -77481,7 +77508,8 @@ function mapSquad(row) {
77481
77508
  status: asString(row.status),
77482
77509
  config: parseJson(asString(row.config)),
77483
77510
  createdAt: asString(row.created_at),
77484
- updatedAt: asString(row.updated_at)
77511
+ updatedAt: asString(row.updated_at),
77512
+ deletedAt: asNullableString(row.deleted_at)
77485
77513
  };
77486
77514
  }
77487
77515
  function mapMember(row) {
@@ -79724,6 +79752,39 @@ router7.delete("/api/squads/:id", async (req, res) => {
79724
79752
  });
79725
79753
  }
79726
79754
  });
79755
+ router7.get("/api/squads/deleted", async (_req, res) => {
79756
+ try {
79757
+ const squads = await listDeletedSquads();
79758
+ res.status(200).json({ squads });
79759
+ } catch (error51) {
79760
+ res.status(500).json({
79761
+ error: "Failed to list deleted squads",
79762
+ details: error51 instanceof Error ? error51.message : "Unknown error"
79763
+ });
79764
+ }
79765
+ });
79766
+ router7.post("/api/squads/:id/restore", async (req, res) => {
79767
+ try {
79768
+ const restored = await restoreSquad(req.params.id);
79769
+ if (!restored) {
79770
+ res.status(404).json({ error: "Squad not found or not deleted" });
79771
+ return;
79772
+ }
79773
+ await logActivity({
79774
+ squadId: restored.id,
79775
+ event: EVENT_NAMES.SQUAD_UPDATED,
79776
+ description: `Restored squad ${restored.name}`,
79777
+ metadata: { repoUrl: restored.repoUrl }
79778
+ });
79779
+ eventBus.emit(EVENT_NAMES.SQUAD_UPDATED, { squad: restored });
79780
+ res.status(200).json({ squad: restored });
79781
+ } catch (error51) {
79782
+ res.status(500).json({
79783
+ error: "Failed to restore squad",
79784
+ details: error51 instanceof Error ? error51.message : "Unknown error"
79785
+ });
79786
+ }
79787
+ });
79727
79788
  router7.get("/api/squads/:id/members", async (req, res) => {
79728
79789
  try {
79729
79790
  const squad = await resolveSquad(req.params.id);
@@ -80971,220 +81032,6 @@ function parseDollarValue(cell) {
80971
81032
  return Number.isNaN(value) ? null : value;
80972
81033
  }
80973
81034
 
80974
- // packages/daemon/src/models/seed.ts
80975
- var SEED_MODELS = [
80976
- {
80977
- id: "gpt-4o-mini",
80978
- displayName: "OpenAI GPT-4o mini",
80979
- premiumMultiplier: 0.33,
80980
- tokenInputMultiplier: 0.015,
80981
- tokenOutputMultiplier: 0.06,
80982
- cachedInputMultiplier: 75e-4,
80983
- tier: "trivial",
80984
- available: true
80985
- },
80986
- {
80987
- id: "gpt-4o",
80988
- displayName: "OpenAI GPT-4o",
80989
- premiumMultiplier: 0.33,
80990
- tokenInputMultiplier: 0.25,
80991
- tokenOutputMultiplier: 1,
80992
- cachedInputMultiplier: 0.125,
80993
- tier: "trivial",
80994
- available: true
80995
- },
80996
- {
80997
- id: "gpt-5-mini",
80998
- displayName: "GPT-5 mini",
80999
- premiumMultiplier: 0.33,
81000
- tokenInputMultiplier: 0.025,
81001
- tokenOutputMultiplier: 0.2,
81002
- cachedInputMultiplier: 25e-4,
81003
- tier: "trivial",
81004
- available: true
81005
- },
81006
- {
81007
- id: "gpt-5.3-codex",
81008
- displayName: "GPT-5.3-Codex",
81009
- premiumMultiplier: 6,
81010
- tokenInputMultiplier: 0.175,
81011
- tokenOutputMultiplier: 1.4,
81012
- cachedInputMultiplier: 0.0175,
81013
- tier: "premium",
81014
- available: true
81015
- },
81016
- {
81017
- id: "gpt-5.4",
81018
- displayName: "GPT-5.4",
81019
- premiumMultiplier: 6,
81020
- tokenInputMultiplier: 0.25,
81021
- tokenOutputMultiplier: 1.5,
81022
- cachedInputMultiplier: 0.025,
81023
- tier: "premium",
81024
- available: true
81025
- },
81026
- {
81027
- id: "gpt-5.4-mini",
81028
- displayName: "GPT-5.4 mini",
81029
- premiumMultiplier: 6,
81030
- tokenInputMultiplier: 0.075,
81031
- tokenOutputMultiplier: 0.45,
81032
- cachedInputMultiplier: 75e-4,
81033
- tier: "premium",
81034
- available: true
81035
- },
81036
- {
81037
- id: "gpt-5.5",
81038
- displayName: "GPT-5.5",
81039
- premiumMultiplier: 57,
81040
- tokenInputMultiplier: 0.5,
81041
- tokenOutputMultiplier: 3,
81042
- cachedInputMultiplier: 0.05,
81043
- tier: "ultra",
81044
- available: true
81045
- },
81046
- {
81047
- id: "claude-sonnet-4",
81048
- displayName: "Claude Sonnet 4",
81049
- premiumMultiplier: 6,
81050
- tokenInputMultiplier: 0.3,
81051
- tokenOutputMultiplier: 1.5,
81052
- cachedInputMultiplier: 0.03,
81053
- tier: "premium",
81054
- available: true
81055
- },
81056
- {
81057
- id: "claude-sonnet-4.5",
81058
- displayName: "Claude Sonnet 4.5",
81059
- premiumMultiplier: 6,
81060
- tokenInputMultiplier: 0.3,
81061
- tokenOutputMultiplier: 1.5,
81062
- cachedInputMultiplier: 0.03,
81063
- tier: "premium",
81064
- available: true
81065
- },
81066
- {
81067
- id: "claude-sonnet-4.6",
81068
- displayName: "Claude Sonnet 4.6",
81069
- premiumMultiplier: 9,
81070
- tokenInputMultiplier: 0.3,
81071
- tokenOutputMultiplier: 1.5,
81072
- cachedInputMultiplier: 0.03,
81073
- tier: "premium",
81074
- available: true
81075
- },
81076
- {
81077
- id: "claude-haiku-4.5",
81078
- displayName: "Claude Haiku 4.5",
81079
- premiumMultiplier: 0.33,
81080
- tokenInputMultiplier: 0.1,
81081
- tokenOutputMultiplier: 0.5,
81082
- cachedInputMultiplier: 0.01,
81083
- tier: "trivial",
81084
- available: true
81085
- },
81086
- {
81087
- id: "claude-opus-4.5",
81088
- displayName: "Claude Opus 4.5",
81089
- premiumMultiplier: 15,
81090
- tokenInputMultiplier: 0.5,
81091
- tokenOutputMultiplier: 2.5,
81092
- cachedInputMultiplier: 0.05,
81093
- tier: "premium",
81094
- available: true
81095
- },
81096
- {
81097
- id: "claude-opus-4.6",
81098
- displayName: "Claude Opus 4.6",
81099
- premiumMultiplier: 27,
81100
- tokenInputMultiplier: 0.5,
81101
- tokenOutputMultiplier: 2.5,
81102
- cachedInputMultiplier: 0.05,
81103
- tier: "ultra",
81104
- available: true
81105
- },
81106
- {
81107
- id: "claude-opus-4.7",
81108
- displayName: "Claude Opus 4.7",
81109
- premiumMultiplier: 27,
81110
- tokenInputMultiplier: 0.5,
81111
- tokenOutputMultiplier: 2.5,
81112
- cachedInputMultiplier: 0.05,
81113
- tier: "ultra",
81114
- available: true
81115
- },
81116
- {
81117
- id: "claude-opus-4.8",
81118
- displayName: "Claude Opus 4.8",
81119
- premiumMultiplier: 27,
81120
- tokenInputMultiplier: 0.5,
81121
- tokenOutputMultiplier: 2.5,
81122
- cachedInputMultiplier: 0.05,
81123
- tier: "ultra",
81124
- available: true
81125
- },
81126
- {
81127
- id: "gemini-2.5-pro",
81128
- displayName: "Gemini 2.5 Pro",
81129
- premiumMultiplier: 1,
81130
- tokenInputMultiplier: 0.125,
81131
- tokenOutputMultiplier: 1,
81132
- cachedInputMultiplier: 0.0125,
81133
- tier: "fast",
81134
- available: true
81135
- },
81136
- {
81137
- id: "gemini-3-flash",
81138
- displayName: "Gemini 3 Flash",
81139
- premiumMultiplier: 0.33,
81140
- tokenInputMultiplier: 0.05,
81141
- tokenOutputMultiplier: 0.3,
81142
- cachedInputMultiplier: 5e-3,
81143
- tier: "trivial",
81144
- available: true
81145
- },
81146
- {
81147
- id: "gemini-3.1-pro",
81148
- displayName: "Gemini 3.1 Pro",
81149
- premiumMultiplier: 6,
81150
- tokenInputMultiplier: 0.2,
81151
- tokenOutputMultiplier: 1.2,
81152
- cachedInputMultiplier: 0.02,
81153
- tier: "premium",
81154
- available: true
81155
- },
81156
- {
81157
- id: "gemini-3.5-flash",
81158
- displayName: "Gemini 3.5 Flash",
81159
- premiumMultiplier: 14,
81160
- tokenInputMultiplier: 0.15,
81161
- tokenOutputMultiplier: 0.9,
81162
- cachedInputMultiplier: 0.015,
81163
- tier: "premium",
81164
- available: true
81165
- },
81166
- {
81167
- id: "raptor-mini",
81168
- displayName: "Raptor mini",
81169
- premiumMultiplier: 0.33,
81170
- tokenInputMultiplier: 0.025,
81171
- tokenOutputMultiplier: 0.2,
81172
- cachedInputMultiplier: 25e-4,
81173
- tier: "trivial",
81174
- available: true
81175
- },
81176
- {
81177
- id: "mai-code-1-flash",
81178
- displayName: "MAI-Code-1-Flash",
81179
- premiumMultiplier: 0.33,
81180
- tokenInputMultiplier: 0.075,
81181
- tokenOutputMultiplier: 0.45,
81182
- cachedInputMultiplier: 75e-4,
81183
- tier: "trivial",
81184
- available: true
81185
- }
81186
- ];
81187
-
81188
81035
  // packages/daemon/src/models/types.ts
81189
81036
  var TIER_RANGES = {
81190
81037
  trivial: { min: 0, max: 0.33 },
@@ -81321,9 +81168,7 @@ async function refreshModelPricing(logger2) {
81321
81168
  await scrapeCopilotPricingIntoMap(modelMap, result, logger2);
81322
81169
  await scrapePremiumPricingIntoMap(modelMap, result, logger2);
81323
81170
  if (!result.catalogFetched && !result.tokenPricingScraped && !result.premiumPricingScraped && !result.copilotPricingScraped) {
81324
- logger2?.warn("All pricing sources failed, using seed data");
81325
- await seedFromFallback();
81326
- result.modelsUpdated = SEED_MODELS.length;
81171
+ logger2?.warn("All pricing sources failed, no models available");
81327
81172
  return result;
81328
81173
  }
81329
81174
  const db = await getDatabase();
@@ -81345,13 +81190,6 @@ async function refreshModelPricing(logger2) {
81345
81190
  }
81346
81191
  return result;
81347
81192
  }
81348
- async function seedFromFallback() {
81349
- const db = await getDatabase();
81350
- const now = nowIso();
81351
- for (const model of SEED_MODELS) {
81352
- await upsertModel(db, { ...model, updatedAt: now });
81353
- }
81354
- }
81355
81193
  async function getModelPricing(modelId) {
81356
81194
  const db = await getDatabase();
81357
81195
  const result = await db.execute({
@@ -83647,10 +83485,22 @@ var squadToolDefinitions = [
83647
83485
  },
83648
83486
  {
83649
83487
  name: "fire_squad",
83650
- description: "Deactivate or delete a squad.",
83488
+ description: "Soft-delete a squad. The squad can be restored later with restore_squad.",
83489
+ parameters: squadIdSchema,
83490
+ skipPermission: true
83491
+ },
83492
+ {
83493
+ name: "restore_squad",
83494
+ description: "Restore a previously deleted squad and all its members.",
83651
83495
  parameters: squadIdSchema,
83652
83496
  skipPermission: true
83653
83497
  },
83498
+ {
83499
+ name: "list_deleted_squads",
83500
+ description: "List all soft-deleted squads that can be restored.",
83501
+ parameters: external_exports.object({}),
83502
+ skipPermission: true
83503
+ },
83654
83504
  {
83655
83505
  name: "list_squads",
83656
83506
  description: "List all squads and their status.",
@@ -83850,7 +83700,7 @@ async function processQueue2(squadId) {
83850
83700
  const next = await getNextQueued(squadId);
83851
83701
  if (next) {
83852
83702
  const freshSquad = await getSquad(squadId);
83853
- if (freshSquad) {
83703
+ if (freshSquad && next.objectiveId) {
83854
83704
  void startAndExecuteInstance(next.id, freshSquad, next.objectiveId);
83855
83705
  }
83856
83706
  }
@@ -83985,13 +83835,28 @@ async function handleFireSquad(rawArgs) {
83985
83835
  if (activeObjectives.length > 0) {
83986
83836
  const updated = await updateSquad(squadId, { status: "inactive" });
83987
83837
  return {
83988
- message: `Squad ${squadId} was deactivated because it still has active objectives.`,
83838
+ message: `Squad ${squadId} was deactivated because it still has active objectives. Use fire_squad again after objectives complete to delete it.`,
83989
83839
  squad: updated,
83990
83840
  activeObjectives
83991
83841
  };
83992
83842
  }
83993
83843
  await deleteSquad(squadId);
83994
- return { message: `Squad ${squadId} was deleted.`, squadId };
83844
+ return {
83845
+ message: `Squad "${squad.name}" has been deleted. It can be restored with restore_squad if needed.`,
83846
+ squadId
83847
+ };
83848
+ }
83849
+ async function handleRestoreSquad(rawArgs) {
83850
+ const { squadId } = squadIdSchema.parse(rawArgs);
83851
+ const restored = await restoreSquad(squadId);
83852
+ if (!restored) {
83853
+ throw new Error(`Squad ${squadId} was not found or is not deleted.`);
83854
+ }
83855
+ eventBus.emit(EVENT_NAMES.SQUAD_UPDATED, { squad: restored });
83856
+ return {
83857
+ message: `Squad "${restored.name}" has been restored.`,
83858
+ squad: restored
83859
+ };
83995
83860
  }
83996
83861
  async function handleDelegateToSquad(rawArgs) {
83997
83862
  const { squadId, objective } = delegateToSquadSchema.parse(rawArgs);
@@ -84056,11 +83921,26 @@ function createSquadToolExecutor(_config) {
84056
83921
  return handleAnalyzeRepo(rawArgs);
84057
83922
  case "fire_squad":
84058
83923
  return handleFireSquad(rawArgs);
83924
+ case "restore_squad":
83925
+ return handleRestoreSquad(rawArgs);
83926
+ case "list_deleted_squads": {
83927
+ const deletedSquads = await listDeletedSquads();
83928
+ if (deletedSquads.length === 0) {
83929
+ return { message: "No deleted squads.", squads: [] };
83930
+ }
83931
+ const list = deletedSquads.map((s) => `${s.id}: ${s.name} (${s.repoOwner}/${s.repoName}) [deleted ${s.deletedAt}]`).join("\n");
83932
+ return { message: list, squads: deletedSquads };
83933
+ }
84059
83934
  case "list_squads": {
84060
83935
  const squads = await listSquads();
83936
+ const deletedCount = (await listDeletedSquads()).length;
83937
+ const suffix = deletedCount > 0 ? `
83938
+
83939
+ ${deletedCount} deleted squad(s) available for restore (use list_deleted_squads to view).` : "";
84061
83940
  return {
84062
- message: formatSquadList(squads),
84063
- squads
83941
+ message: formatSquadList(squads) + suffix,
83942
+ squads,
83943
+ deletedCount
84064
83944
  };
84065
83945
  }
84066
83946
  case "get_squad_status": {
@@ -84807,8 +84687,7 @@ async function main() {
84807
84687
  logger2.info("Database initialized");
84808
84688
  const pricingResult = await refreshModelPricing(logger2);
84809
84689
  if (pricingResult.modelsUpdated === 0) {
84810
- logger2.warn("Model pricing refresh returned 0 models, seeding with fallback");
84811
- await seedFromFallback();
84690
+ logger2.warn("Model pricing refresh returned 0 models");
84812
84691
  }
84813
84692
  logger2.info({ modelsUpdated: pricingResult.modelsUpdated }, "Model pricing initialized");
84814
84693
  await scanSkills();