heyio 4.3.3 → 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.
@@ -80,7 +80,7 @@ var init_constants = __esm({
80
80
  "packages/shared/dist/constants.js"() {
81
81
  "use strict";
82
82
  APP_NAME = "io";
83
- APP_VERSION = "4.3.3";
83
+ APP_VERSION = "4.3.4";
84
84
  API_PORT = 7777;
85
85
  API_HOST = "0.0.0.0";
86
86
  DEFAULT_MODEL = "gpt-4.1-mini";
@@ -69533,18 +69533,21 @@ var init_manager2 = __esm({
69533
69533
  });
69534
69534
 
69535
69535
  // packages/daemon/src/squad/model-selector.ts
69536
- import { CopilotClient as CopilotClient2, approveAll as approveAll2 } from "@github/copilot-sdk";
69536
+ function classifyTaskComplexity(taskDescription) {
69537
+ const tiers = ["ultra", "premium", "standard", "fast", "trivial"];
69538
+ for (const tier of tiers) {
69539
+ if (TIER_KEYWORDS[tier].some((pattern) => pattern.test(taskDescription))) {
69540
+ return tier;
69541
+ }
69542
+ }
69543
+ return "standard";
69544
+ }
69537
69545
  async function selectModelForTask(taskDescription) {
69538
69546
  const classifierModel = await getCheapestAvailableModel();
69539
69547
  if (!classifierModel) {
69540
69548
  throw new Error("No models available in pricing database");
69541
69549
  }
69542
- let tier;
69543
- try {
69544
- tier = await classifyTaskComplexity(taskDescription, classifierModel.id);
69545
- } catch {
69546
- return classifierModel.id;
69547
- }
69550
+ const tier = classifyTaskComplexity(taskDescription);
69548
69551
  const selectedModel = await getCheapestInTier(tier);
69549
69552
  if (selectedModel) {
69550
69553
  return selectedModel.id;
@@ -69558,46 +69561,18 @@ async function selectModelForTask(taskDescription) {
69558
69561
  }
69559
69562
  return classifierModel.id;
69560
69563
  }
69561
- async function classifyTaskComplexity(taskDescription, modelId) {
69562
- let client2 = null;
69563
- try {
69564
- client2 = new CopilotClient2();
69565
- await client2.start();
69566
- const session = await client2.createSession({
69567
- model: modelId,
69568
- onPermissionRequest: approveAll2,
69569
- systemMessage: { content: CLASSIFICATION_PROMPT }
69570
- });
69571
- try {
69572
- const response = await session.sendAndWait({ prompt: `Task: ${taskDescription}` }, 15e3);
69573
- const raw = (response.text ?? "").trim().toLowerCase();
69574
- const tier = VALID_TIERS.find((t) => raw.includes(t));
69575
- return tier ?? "standard";
69576
- } finally {
69577
- await session.disconnect().catch(() => void 0);
69578
- }
69579
- } finally {
69580
- if (client2) {
69581
- await client2.stop().catch(() => void 0);
69582
- }
69583
- }
69584
- }
69585
- var VALID_TIERS, CLASSIFICATION_PROMPT;
69564
+ var TIER_KEYWORDS;
69586
69565
  var init_model_selector = __esm({
69587
69566
  "packages/daemon/src/squad/model-selector.ts"() {
69588
69567
  "use strict";
69589
69568
  init_registry();
69590
- VALID_TIERS = ["trivial", "fast", "standard", "premium", "ultra"];
69591
- CLASSIFICATION_PROMPT = `You are a task complexity classifier. Given a task description, classify its complexity into exactly one tier.
69592
-
69593
- Tiers (from simplest to most complex):
69594
- - trivial: Typos, renames, comment changes, config tweaks, formatting
69595
- - fast: Simple bug fixes, small features, documentation updates, single-file changes
69596
- - standard: Feature implementation, multi-file changes, moderate refactoring
69597
- - premium: Architecture changes, complex refactoring, security work, performance optimization
69598
- - ultra: System-wide redesigns, critical infrastructure, cross-cutting concerns
69599
-
69600
- Reply with ONLY the tier name (one word, lowercase). Nothing else.`;
69569
+ TIER_KEYWORDS = {
69570
+ ultra: [/system[- ]wide/i, /redesign/i, /infrastructure/i, /cross[- ]cutting/i, /migration/i],
69571
+ premium: [/architect/i, /security/i, /performance/i, /complex refactor/i, /optimization/i],
69572
+ standard: [/implement/i, /feature/i, /multi[- ]file/i, /refactor/i, /integration/i],
69573
+ fast: [/fix/i, /bug/i, /update/i, /documentation/i, /single[- ]file/i, /small/i],
69574
+ trivial: [/typo/i, /rename/i, /comment/i, /config/i, /format/i]
69575
+ };
69601
69576
  }
69602
69577
  });
69603
69578
 
@@ -69638,8 +69613,8 @@ import { mkdir as mkdir9, readFile as readFile7, readdir as readdir5, stat as st
69638
69613
  import { dirname as dirname8, extname as extname3, isAbsolute, join as join11, relative as relative3, resolve as resolve4 } from "node:path";
69639
69614
  import { promisify as promisify3 } from "node:util";
69640
69615
  import {
69641
- CopilotClient as CopilotClient3,
69642
- approveAll as approveAll3,
69616
+ CopilotClient as CopilotClient2,
69617
+ approveAll as approveAll2,
69643
69618
  defineTool
69644
69619
  } from "@github/copilot-sdk";
69645
69620
  function createEmptyUsage() {
@@ -69898,15 +69873,15 @@ async function executeAgentTask(member, task, worktreePath, options2) {
69898
69873
  const mcpServerNote = options2?.mcpServers?.length ? `Available MCP server labels: ${options2.mcpServers.join(", ")}.` : "No additional MCP servers were configured for this run.";
69899
69874
  let client2 = null;
69900
69875
  try {
69901
- client2 = new CopilotClient3({ workingDirectory: worktreePath });
69876
+ client2 = new CopilotClient2({ workingDirectory: worktreePath });
69902
69877
  await client2.start();
69903
69878
  const model = member.model ? stripVendorPrefix(member.model) : await selectModelForTask(task.description);
69904
- const session = await client2.createSession({
69879
+ const sessionPromise = client2.createSession({
69905
69880
  model,
69906
69881
  workingDirectory: worktreePath,
69907
69882
  tools,
69908
69883
  availableTools: ["custom:*"],
69909
- onPermissionRequest: approveAll3,
69884
+ onPermissionRequest: approveAll2,
69910
69885
  systemMessage: {
69911
69886
  content: `${member.systemPrompt}
69912
69887
 
@@ -69916,6 +69891,15 @@ ${historyContext}
69916
69891
  ${mcpServerNote}${options2?.instancePromptSuffix ?? ""}`
69917
69892
  }
69918
69893
  });
69894
+ const session = await Promise.race([
69895
+ sessionPromise,
69896
+ new Promise(
69897
+ (_, reject) => setTimeout(
69898
+ () => reject(new Error(`Session creation timed out after ${SESSION_CREATE_TIMEOUT_MS}ms`)),
69899
+ SESSION_CREATE_TIMEOUT_MS
69900
+ )
69901
+ )
69902
+ ]);
69919
69903
  session.on("assistant.usage", (event) => {
69920
69904
  usageEvents.push(event.data);
69921
69905
  mergeUsage(usage, event.data);
@@ -69954,7 +69938,7 @@ Work only inside the current worktree. Summarize the concrete changes you made,
69954
69938
  }
69955
69939
  }
69956
69940
  }
69957
- var execAsync3, MAX_FILE_SIZE, MAX_LIST_RESULTS, MAX_SEARCH_RESULTS;
69941
+ var execAsync3, MAX_FILE_SIZE, MAX_LIST_RESULTS, MAX_SEARCH_RESULTS, SESSION_CREATE_TIMEOUT_MS;
69958
69942
  var init_agent = __esm({
69959
69943
  "packages/daemon/src/execution/agent.ts"() {
69960
69944
  "use strict";
@@ -69966,6 +69950,7 @@ var init_agent = __esm({
69966
69950
  MAX_FILE_SIZE = 2e5;
69967
69951
  MAX_LIST_RESULTS = 200;
69968
69952
  MAX_SEARCH_RESULTS = 100;
69953
+ SESSION_CREATE_TIMEOUT_MS = 3e4;
69969
69954
  }
69970
69955
  });
69971
69956
 
@@ -70057,7 +70042,7 @@ import { exec as exec4 } from "node:child_process";
70057
70042
  import { access, readFile as readFile8 } from "node:fs/promises";
70058
70043
  import { join as join12 } from "node:path";
70059
70044
  import { promisify as promisify4 } from "node:util";
70060
- import { CopilotClient as CopilotClient4, approveAll as approveAll4 } from "@github/copilot-sdk";
70045
+ import { CopilotClient as CopilotClient3, approveAll as approveAll3 } from "@github/copilot-sdk";
70061
70046
  async function fileExists(path) {
70062
70047
  try {
70063
70048
  await access(path);
@@ -70151,13 +70136,13 @@ Return strict JSON in this shape:
70151
70136
  }`;
70152
70137
  let client2 = null;
70153
70138
  try {
70154
- client2 = new CopilotClient4({ workingDirectory: repoPath });
70139
+ client2 = new CopilotClient3({ workingDirectory: repoPath });
70155
70140
  await client2.start();
70156
70141
  const model = await selectModelForTask(`Create implementation plan: ${objective.description}`);
70157
70142
  const session = await client2.createSession({
70158
70143
  model,
70159
70144
  workingDirectory: repoPath,
70160
- onPermissionRequest: approveAll4,
70145
+ onPermissionRequest: approveAll3,
70161
70146
  systemMessage: {
70162
70147
  content: `${TEAM_LEAD_PROMPT}
70163
70148
 
@@ -70277,7 +70262,7 @@ var init_pr = __esm({
70277
70262
  // packages/daemon/src/execution/qa.ts
70278
70263
  import { exec as exec6 } from "node:child_process";
70279
70264
  import { promisify as promisify6 } from "node:util";
70280
- import { CopilotClient as CopilotClient5, approveAll as approveAll5 } from "@github/copilot-sdk";
70265
+ import { CopilotClient as CopilotClient4, approveAll as approveAll4 } from "@github/copilot-sdk";
70281
70266
  function extractJsonObject2(content) {
70282
70267
  const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/i);
70283
70268
  if (fenced?.[1]) {
@@ -70315,13 +70300,13 @@ Return strict JSON:
70315
70300
  }`;
70316
70301
  let client2 = null;
70317
70302
  try {
70318
- client2 = new CopilotClient5({ workingDirectory: worktreePath });
70303
+ client2 = new CopilotClient4({ workingDirectory: worktreePath });
70319
70304
  await client2.start();
70320
70305
  const model = qaMember.model ? stripVendorPrefix(qaMember.model) : await selectModelForTask(`QA review: ${objective.description}`);
70321
70306
  const session = await client2.createSession({
70322
70307
  model,
70323
70308
  workingDirectory: worktreePath,
70324
- onPermissionRequest: approveAll5,
70309
+ onPermissionRequest: approveAll4,
70325
70310
  systemMessage: {
70326
70311
  content: QA_PROMPT
70327
70312
  }
@@ -70405,7 +70390,7 @@ var init_qa = __esm({
70405
70390
  });
70406
70391
 
70407
70392
  // packages/daemon/src/execution/review.ts
70408
- import { CopilotClient as CopilotClient6, approveAll as approveAll6 } from "@github/copilot-sdk";
70393
+ import { CopilotClient as CopilotClient5, approveAll as approveAll5 } from "@github/copilot-sdk";
70409
70394
  function extractJsonObject3(content) {
70410
70395
  const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/i);
70411
70396
  if (fenced?.[1]) {
@@ -70450,12 +70435,12 @@ Return strict JSON:
70450
70435
  }`;
70451
70436
  let client2 = null;
70452
70437
  try {
70453
- client2 = new CopilotClient6();
70438
+ client2 = new CopilotClient5();
70454
70439
  await client2.start();
70455
70440
  const model = teamLead.model ? stripVendorPrefix(teamLead.model) : await selectModelForTask(`Code review: ${objective.description}`);
70456
70441
  const session = await client2.createSession({
70457
70442
  model,
70458
- onPermissionRequest: approveAll6,
70443
+ onPermissionRequest: approveAll5,
70459
70444
  systemMessage: {
70460
70445
  content: `${TEAM_LEAD_PROMPT}
70461
70446
 
@@ -70617,60 +70602,49 @@ async function executePendingTasks(objective, members, worktreePath, mcpServers,
70617
70602
  if (pendingTasks.length === 0) {
70618
70603
  return getTasksForObjective(objective.id);
70619
70604
  }
70620
- const results = await Promise.allSettled(
70621
- pendingTasks.map(async (task) => {
70622
- const member = members.find((candidate) => candidate.id === task.assigneeId);
70623
- if (!member) {
70624
- const failedTask = await markTaskFailed(
70625
- task.id,
70626
- "No squad member matched the task assignee."
70627
- );
70628
- eventBus.emit(EVENT_NAMES.TASK_FAILED, {
70629
- task: failedTask,
70630
- agentName: "unassigned",
70631
- reason: failedTask.result ?? "No assignee"
70632
- });
70633
- throw new Error(`Task ${task.id} has no matching assignee`);
70634
- }
70635
- const inProgressTask = await updateTaskStatus(
70605
+ for (const task of pendingTasks) {
70606
+ const member = members.find((candidate) => candidate.id === task.assigneeId);
70607
+ if (!member) {
70608
+ const failedTask = await markTaskFailed(
70636
70609
  task.id,
70637
- "in_progress",
70638
- task.result ?? void 0
70610
+ "No squad member matched the task assignee."
70639
70611
  );
70640
- const startedTask = inProgressTask ?? task;
70641
- eventBus.emit(EVENT_NAMES.TASK_STARTED, { task: startedTask, agentName: member.name });
70642
- eventBus.emit(EVENT_NAMES.AGENT_EXECUTING, {
70643
- squadId: objective.squadId,
70644
- agentId: member.id,
70645
- taskId: task.id
70646
- });
70647
- const execution = await executeAgentTask(member, task, worktreePath, {
70648
- mcpServers,
70649
- instancePromptSuffix
70612
+ eventBus.emit(EVENT_NAMES.TASK_FAILED, {
70613
+ task: failedTask,
70614
+ agentName: "unassigned",
70615
+ reason: failedTask.result ?? "No assignee"
70650
70616
  });
70651
- if (!execution.success) {
70652
- const failedTask = await markTaskFailed(task.id, execution.result);
70653
- eventBus.emit(EVENT_NAMES.TASK_FAILED, {
70654
- task: failedTask,
70655
- agentName: member.name,
70656
- reason: execution.result
70657
- });
70658
- throw new Error(execution.result);
70659
- }
70660
- const completedTask = await markTaskComplete(task.id, execution.result);
70661
- await extractLearnings(member.id, member.squadId, execution.result);
70662
- eventBus.emit(EVENT_NAMES.TASK_COMPLETED, { task: completedTask, agentName: member.name });
70663
- eventBus.emit(EVENT_NAMES.AGENT_COMPLETED, {
70664
- squadId: objective.squadId,
70665
- agentId: member.id,
70666
- taskId: task.id
70617
+ throw new Error(`Task ${task.id} has no matching assignee`);
70618
+ }
70619
+ const inProgressTask = await updateTaskStatus(task.id, "in_progress", task.result ?? void 0);
70620
+ const startedTask = inProgressTask ?? task;
70621
+ eventBus.emit(EVENT_NAMES.TASK_STARTED, { task: startedTask, agentName: member.name });
70622
+ eventBus.emit(EVENT_NAMES.AGENT_EXECUTING, {
70623
+ squadId: objective.squadId,
70624
+ agentId: member.id,
70625
+ taskId: task.id
70626
+ });
70627
+ const execution = await executeAgentTask(member, task, worktreePath, {
70628
+ mcpServers,
70629
+ instancePromptSuffix
70630
+ });
70631
+ if (!execution.success) {
70632
+ const failedTask = await markTaskFailed(task.id, execution.result);
70633
+ eventBus.emit(EVENT_NAMES.TASK_FAILED, {
70634
+ task: failedTask,
70635
+ agentName: member.name,
70636
+ reason: execution.result
70667
70637
  });
70668
- return completedTask;
70669
- })
70670
- );
70671
- const failed = results.find((result) => result.status === "rejected");
70672
- if (failed && failed.status === "rejected") {
70673
- throw failed.reason instanceof Error ? failed.reason : new Error(String(failed.reason));
70638
+ throw new Error(execution.result);
70639
+ }
70640
+ const completedTask = await markTaskComplete(task.id, execution.result);
70641
+ await extractLearnings(member.id, member.squadId, execution.result);
70642
+ eventBus.emit(EVENT_NAMES.TASK_COMPLETED, { task: completedTask, agentName: member.name });
70643
+ eventBus.emit(EVENT_NAMES.AGENT_COMPLETED, {
70644
+ squadId: objective.squadId,
70645
+ agentId: member.id,
70646
+ taskId: task.id
70647
+ });
70674
70648
  }
70675
70649
  return getTasksForObjective(objective.id);
70676
70650
  }