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.
- package/dist/daemon/cli.js +85 -110
- package/dist/daemon/index.js +882 -970
- package/package.json +1 -1
package/dist/daemon/cli.js
CHANGED
|
@@ -80,7 +80,7 @@ var init_constants = __esm({
|
|
|
80
80
|
"packages/shared/dist/constants.js"() {
|
|
81
81
|
"use strict";
|
|
82
82
|
APP_NAME = "io";
|
|
83
|
-
APP_VERSION = "4.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";
|
|
@@ -68368,6 +68368,7 @@ async function refreshModelPricing(logger2) {
|
|
|
68368
68368
|
}
|
|
68369
68369
|
const db = await getDatabase();
|
|
68370
68370
|
const now = nowIso();
|
|
68371
|
+
await db.execute("DELETE FROM model_pricing WHERE id LIKE '%/%'");
|
|
68371
68372
|
for (const model of modelMap.values()) {
|
|
68372
68373
|
if (model.tokenInputMultiplier == null) {
|
|
68373
68374
|
continue;
|
|
@@ -68473,7 +68474,7 @@ async function upsertModel(db, model) {
|
|
|
68473
68474
|
}
|
|
68474
68475
|
function rowToModelPricing(row) {
|
|
68475
68476
|
return {
|
|
68476
|
-
id: asString(row.id),
|
|
68477
|
+
id: stripVendorPrefix(asString(row.id)),
|
|
68477
68478
|
displayName: asString(row.display_name),
|
|
68478
68479
|
premiumMultiplier: asNullableNumber(row.premium_multiplier),
|
|
68479
68480
|
tokenInputMultiplier: asNullableNumber(row.token_input_multiplier),
|
|
@@ -69532,18 +69533,21 @@ var init_manager2 = __esm({
|
|
|
69532
69533
|
});
|
|
69533
69534
|
|
|
69534
69535
|
// packages/daemon/src/squad/model-selector.ts
|
|
69535
|
-
|
|
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
|
+
}
|
|
69536
69545
|
async function selectModelForTask(taskDescription) {
|
|
69537
69546
|
const classifierModel = await getCheapestAvailableModel();
|
|
69538
69547
|
if (!classifierModel) {
|
|
69539
69548
|
throw new Error("No models available in pricing database");
|
|
69540
69549
|
}
|
|
69541
|
-
|
|
69542
|
-
try {
|
|
69543
|
-
tier = await classifyTaskComplexity(taskDescription, classifierModel.id);
|
|
69544
|
-
} catch {
|
|
69545
|
-
return classifierModel.id;
|
|
69546
|
-
}
|
|
69550
|
+
const tier = classifyTaskComplexity(taskDescription);
|
|
69547
69551
|
const selectedModel = await getCheapestInTier(tier);
|
|
69548
69552
|
if (selectedModel) {
|
|
69549
69553
|
return selectedModel.id;
|
|
@@ -69557,46 +69561,18 @@ async function selectModelForTask(taskDescription) {
|
|
|
69557
69561
|
}
|
|
69558
69562
|
return classifierModel.id;
|
|
69559
69563
|
}
|
|
69560
|
-
|
|
69561
|
-
let client2 = null;
|
|
69562
|
-
try {
|
|
69563
|
-
client2 = new CopilotClient2();
|
|
69564
|
-
await client2.start();
|
|
69565
|
-
const session = await client2.createSession({
|
|
69566
|
-
model: modelId,
|
|
69567
|
-
onPermissionRequest: approveAll2,
|
|
69568
|
-
systemMessage: { content: CLASSIFICATION_PROMPT }
|
|
69569
|
-
});
|
|
69570
|
-
try {
|
|
69571
|
-
const response = await session.sendAndWait({ prompt: `Task: ${taskDescription}` }, 15e3);
|
|
69572
|
-
const raw = (response.text ?? "").trim().toLowerCase();
|
|
69573
|
-
const tier = VALID_TIERS.find((t) => raw.includes(t));
|
|
69574
|
-
return tier ?? "standard";
|
|
69575
|
-
} finally {
|
|
69576
|
-
await session.disconnect().catch(() => void 0);
|
|
69577
|
-
}
|
|
69578
|
-
} finally {
|
|
69579
|
-
if (client2) {
|
|
69580
|
-
await client2.stop().catch(() => void 0);
|
|
69581
|
-
}
|
|
69582
|
-
}
|
|
69583
|
-
}
|
|
69584
|
-
var VALID_TIERS, CLASSIFICATION_PROMPT;
|
|
69564
|
+
var TIER_KEYWORDS;
|
|
69585
69565
|
var init_model_selector = __esm({
|
|
69586
69566
|
"packages/daemon/src/squad/model-selector.ts"() {
|
|
69587
69567
|
"use strict";
|
|
69588
69568
|
init_registry();
|
|
69589
|
-
|
|
69590
|
-
|
|
69591
|
-
|
|
69592
|
-
|
|
69593
|
-
|
|
69594
|
-
|
|
69595
|
-
|
|
69596
|
-
- premium: Architecture changes, complex refactoring, security work, performance optimization
|
|
69597
|
-
- ultra: System-wide redesigns, critical infrastructure, cross-cutting concerns
|
|
69598
|
-
|
|
69599
|
-
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
|
+
};
|
|
69600
69576
|
}
|
|
69601
69577
|
});
|
|
69602
69578
|
|
|
@@ -69637,8 +69613,8 @@ import { mkdir as mkdir9, readFile as readFile7, readdir as readdir5, stat as st
|
|
|
69637
69613
|
import { dirname as dirname8, extname as extname3, isAbsolute, join as join11, relative as relative3, resolve as resolve4 } from "node:path";
|
|
69638
69614
|
import { promisify as promisify3 } from "node:util";
|
|
69639
69615
|
import {
|
|
69640
|
-
CopilotClient as
|
|
69641
|
-
approveAll as
|
|
69616
|
+
CopilotClient as CopilotClient2,
|
|
69617
|
+
approveAll as approveAll2,
|
|
69642
69618
|
defineTool
|
|
69643
69619
|
} from "@github/copilot-sdk";
|
|
69644
69620
|
function createEmptyUsage() {
|
|
@@ -69897,15 +69873,15 @@ async function executeAgentTask(member, task, worktreePath, options2) {
|
|
|
69897
69873
|
const mcpServerNote = options2?.mcpServers?.length ? `Available MCP server labels: ${options2.mcpServers.join(", ")}.` : "No additional MCP servers were configured for this run.";
|
|
69898
69874
|
let client2 = null;
|
|
69899
69875
|
try {
|
|
69900
|
-
client2 = new
|
|
69876
|
+
client2 = new CopilotClient2({ workingDirectory: worktreePath });
|
|
69901
69877
|
await client2.start();
|
|
69902
69878
|
const model = member.model ? stripVendorPrefix(member.model) : await selectModelForTask(task.description);
|
|
69903
|
-
const
|
|
69879
|
+
const sessionPromise = client2.createSession({
|
|
69904
69880
|
model,
|
|
69905
69881
|
workingDirectory: worktreePath,
|
|
69906
69882
|
tools,
|
|
69907
69883
|
availableTools: ["custom:*"],
|
|
69908
|
-
onPermissionRequest:
|
|
69884
|
+
onPermissionRequest: approveAll2,
|
|
69909
69885
|
systemMessage: {
|
|
69910
69886
|
content: `${member.systemPrompt}
|
|
69911
69887
|
|
|
@@ -69915,6 +69891,15 @@ ${historyContext}
|
|
|
69915
69891
|
${mcpServerNote}${options2?.instancePromptSuffix ?? ""}`
|
|
69916
69892
|
}
|
|
69917
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
|
+
]);
|
|
69918
69903
|
session.on("assistant.usage", (event) => {
|
|
69919
69904
|
usageEvents.push(event.data);
|
|
69920
69905
|
mergeUsage(usage, event.data);
|
|
@@ -69953,7 +69938,7 @@ Work only inside the current worktree. Summarize the concrete changes you made,
|
|
|
69953
69938
|
}
|
|
69954
69939
|
}
|
|
69955
69940
|
}
|
|
69956
|
-
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;
|
|
69957
69942
|
var init_agent = __esm({
|
|
69958
69943
|
"packages/daemon/src/execution/agent.ts"() {
|
|
69959
69944
|
"use strict";
|
|
@@ -69965,6 +69950,7 @@ var init_agent = __esm({
|
|
|
69965
69950
|
MAX_FILE_SIZE = 2e5;
|
|
69966
69951
|
MAX_LIST_RESULTS = 200;
|
|
69967
69952
|
MAX_SEARCH_RESULTS = 100;
|
|
69953
|
+
SESSION_CREATE_TIMEOUT_MS = 3e4;
|
|
69968
69954
|
}
|
|
69969
69955
|
});
|
|
69970
69956
|
|
|
@@ -70056,7 +70042,7 @@ import { exec as exec4 } from "node:child_process";
|
|
|
70056
70042
|
import { access, readFile as readFile8 } from "node:fs/promises";
|
|
70057
70043
|
import { join as join12 } from "node:path";
|
|
70058
70044
|
import { promisify as promisify4 } from "node:util";
|
|
70059
|
-
import { CopilotClient as
|
|
70045
|
+
import { CopilotClient as CopilotClient3, approveAll as approveAll3 } from "@github/copilot-sdk";
|
|
70060
70046
|
async function fileExists(path) {
|
|
70061
70047
|
try {
|
|
70062
70048
|
await access(path);
|
|
@@ -70150,13 +70136,13 @@ Return strict JSON in this shape:
|
|
|
70150
70136
|
}`;
|
|
70151
70137
|
let client2 = null;
|
|
70152
70138
|
try {
|
|
70153
|
-
client2 = new
|
|
70139
|
+
client2 = new CopilotClient3({ workingDirectory: repoPath });
|
|
70154
70140
|
await client2.start();
|
|
70155
70141
|
const model = await selectModelForTask(`Create implementation plan: ${objective.description}`);
|
|
70156
70142
|
const session = await client2.createSession({
|
|
70157
70143
|
model,
|
|
70158
70144
|
workingDirectory: repoPath,
|
|
70159
|
-
onPermissionRequest:
|
|
70145
|
+
onPermissionRequest: approveAll3,
|
|
70160
70146
|
systemMessage: {
|
|
70161
70147
|
content: `${TEAM_LEAD_PROMPT}
|
|
70162
70148
|
|
|
@@ -70276,7 +70262,7 @@ var init_pr = __esm({
|
|
|
70276
70262
|
// packages/daemon/src/execution/qa.ts
|
|
70277
70263
|
import { exec as exec6 } from "node:child_process";
|
|
70278
70264
|
import { promisify as promisify6 } from "node:util";
|
|
70279
|
-
import { CopilotClient as
|
|
70265
|
+
import { CopilotClient as CopilotClient4, approveAll as approveAll4 } from "@github/copilot-sdk";
|
|
70280
70266
|
function extractJsonObject2(content) {
|
|
70281
70267
|
const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
70282
70268
|
if (fenced?.[1]) {
|
|
@@ -70314,13 +70300,13 @@ Return strict JSON:
|
|
|
70314
70300
|
}`;
|
|
70315
70301
|
let client2 = null;
|
|
70316
70302
|
try {
|
|
70317
|
-
client2 = new
|
|
70303
|
+
client2 = new CopilotClient4({ workingDirectory: worktreePath });
|
|
70318
70304
|
await client2.start();
|
|
70319
70305
|
const model = qaMember.model ? stripVendorPrefix(qaMember.model) : await selectModelForTask(`QA review: ${objective.description}`);
|
|
70320
70306
|
const session = await client2.createSession({
|
|
70321
70307
|
model,
|
|
70322
70308
|
workingDirectory: worktreePath,
|
|
70323
|
-
onPermissionRequest:
|
|
70309
|
+
onPermissionRequest: approveAll4,
|
|
70324
70310
|
systemMessage: {
|
|
70325
70311
|
content: QA_PROMPT
|
|
70326
70312
|
}
|
|
@@ -70404,7 +70390,7 @@ var init_qa = __esm({
|
|
|
70404
70390
|
});
|
|
70405
70391
|
|
|
70406
70392
|
// packages/daemon/src/execution/review.ts
|
|
70407
|
-
import { CopilotClient as
|
|
70393
|
+
import { CopilotClient as CopilotClient5, approveAll as approveAll5 } from "@github/copilot-sdk";
|
|
70408
70394
|
function extractJsonObject3(content) {
|
|
70409
70395
|
const fenced = content.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
70410
70396
|
if (fenced?.[1]) {
|
|
@@ -70449,12 +70435,12 @@ Return strict JSON:
|
|
|
70449
70435
|
}`;
|
|
70450
70436
|
let client2 = null;
|
|
70451
70437
|
try {
|
|
70452
|
-
client2 = new
|
|
70438
|
+
client2 = new CopilotClient5();
|
|
70453
70439
|
await client2.start();
|
|
70454
70440
|
const model = teamLead.model ? stripVendorPrefix(teamLead.model) : await selectModelForTask(`Code review: ${objective.description}`);
|
|
70455
70441
|
const session = await client2.createSession({
|
|
70456
70442
|
model,
|
|
70457
|
-
onPermissionRequest:
|
|
70443
|
+
onPermissionRequest: approveAll5,
|
|
70458
70444
|
systemMessage: {
|
|
70459
70445
|
content: `${TEAM_LEAD_PROMPT}
|
|
70460
70446
|
|
|
@@ -70616,60 +70602,49 @@ async function executePendingTasks(objective, members, worktreePath, mcpServers,
|
|
|
70616
70602
|
if (pendingTasks.length === 0) {
|
|
70617
70603
|
return getTasksForObjective(objective.id);
|
|
70618
70604
|
}
|
|
70619
|
-
const
|
|
70620
|
-
|
|
70621
|
-
|
|
70622
|
-
|
|
70623
|
-
const failedTask = await markTaskFailed(
|
|
70624
|
-
task.id,
|
|
70625
|
-
"No squad member matched the task assignee."
|
|
70626
|
-
);
|
|
70627
|
-
eventBus.emit(EVENT_NAMES.TASK_FAILED, {
|
|
70628
|
-
task: failedTask,
|
|
70629
|
-
agentName: "unassigned",
|
|
70630
|
-
reason: failedTask.result ?? "No assignee"
|
|
70631
|
-
});
|
|
70632
|
-
throw new Error(`Task ${task.id} has no matching assignee`);
|
|
70633
|
-
}
|
|
70634
|
-
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(
|
|
70635
70609
|
task.id,
|
|
70636
|
-
"
|
|
70637
|
-
task.result ?? void 0
|
|
70610
|
+
"No squad member matched the task assignee."
|
|
70638
70611
|
);
|
|
70639
|
-
|
|
70640
|
-
|
|
70641
|
-
|
|
70642
|
-
|
|
70643
|
-
agentId: member.id,
|
|
70644
|
-
taskId: task.id
|
|
70645
|
-
});
|
|
70646
|
-
const execution = await executeAgentTask(member, task, worktreePath, {
|
|
70647
|
-
mcpServers,
|
|
70648
|
-
instancePromptSuffix
|
|
70612
|
+
eventBus.emit(EVENT_NAMES.TASK_FAILED, {
|
|
70613
|
+
task: failedTask,
|
|
70614
|
+
agentName: "unassigned",
|
|
70615
|
+
reason: failedTask.result ?? "No assignee"
|
|
70649
70616
|
});
|
|
70650
|
-
|
|
70651
|
-
|
|
70652
|
-
|
|
70653
|
-
|
|
70654
|
-
|
|
70655
|
-
|
|
70656
|
-
|
|
70657
|
-
|
|
70658
|
-
|
|
70659
|
-
|
|
70660
|
-
|
|
70661
|
-
|
|
70662
|
-
|
|
70663
|
-
|
|
70664
|
-
|
|
70665
|
-
|
|
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
|
|
70666
70637
|
});
|
|
70667
|
-
|
|
70668
|
-
}
|
|
70669
|
-
|
|
70670
|
-
|
|
70671
|
-
|
|
70672
|
-
|
|
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
|
+
});
|
|
70673
70648
|
}
|
|
70674
70649
|
return getTasksForObjective(objective.id);
|
|
70675
70650
|
}
|