llm-party-cli 0.9.0 → 0.11.0
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/README.md +37 -7
- package/dist/index.js +1002 -332
- package/package.json +2 -3
- package/prompts/artifacts.md +49 -93
- package/prompts/base.md +80 -209
- package/prompts/obsidian.md +30 -102
package/dist/index.js
CHANGED
|
@@ -3284,7 +3284,7 @@ var require_main = __commonJS((exports) => {
|
|
|
3284
3284
|
});
|
|
3285
3285
|
|
|
3286
3286
|
// src/index.ts
|
|
3287
|
-
import { readFile as
|
|
3287
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
3288
3288
|
import path11 from "path";
|
|
3289
3289
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3290
3290
|
|
|
@@ -36264,43 +36264,6 @@ function Show(props) {
|
|
|
36264
36264
|
return props.fallback;
|
|
36265
36265
|
}, undefined, undefined);
|
|
36266
36266
|
}
|
|
36267
|
-
function Switch(props) {
|
|
36268
|
-
const chs = children(() => props.children);
|
|
36269
|
-
const switchFunc = createMemo(() => {
|
|
36270
|
-
const ch = chs();
|
|
36271
|
-
const mps = Array.isArray(ch) ? ch : [ch];
|
|
36272
|
-
let func = () => {
|
|
36273
|
-
return;
|
|
36274
|
-
};
|
|
36275
|
-
for (let i = 0;i < mps.length; i++) {
|
|
36276
|
-
const index = i;
|
|
36277
|
-
const mp = mps[i];
|
|
36278
|
-
const prevFunc = func;
|
|
36279
|
-
const conditionValue = createMemo(() => prevFunc() ? undefined : mp.when, undefined, undefined);
|
|
36280
|
-
const condition = mp.keyed ? conditionValue : createMemo(conditionValue, undefined, {
|
|
36281
|
-
equals: (a, b2) => !a === !b2
|
|
36282
|
-
});
|
|
36283
|
-
func = () => prevFunc() || (condition() ? [index, conditionValue, mp] : undefined);
|
|
36284
|
-
}
|
|
36285
|
-
return func;
|
|
36286
|
-
});
|
|
36287
|
-
return createMemo(() => {
|
|
36288
|
-
const sel = switchFunc()();
|
|
36289
|
-
if (!sel)
|
|
36290
|
-
return props.fallback;
|
|
36291
|
-
const [index, conditionValue, mp] = sel;
|
|
36292
|
-
const child = mp.children;
|
|
36293
|
-
const fn = typeof child === "function" && child.length > 0;
|
|
36294
|
-
return fn ? untrack(() => child(mp.keyed ? conditionValue() : () => {
|
|
36295
|
-
if (untrack(switchFunc)()?.[0] !== index)
|
|
36296
|
-
throw narrowedError("Match");
|
|
36297
|
-
return conditionValue();
|
|
36298
|
-
})) : child;
|
|
36299
|
-
}, undefined, undefined);
|
|
36300
|
-
}
|
|
36301
|
-
function Match(props) {
|
|
36302
|
-
return props;
|
|
36303
|
-
}
|
|
36304
36267
|
|
|
36305
36268
|
// node_modules/entities/dist/esm/decode-codepoint.js
|
|
36306
36269
|
var _a;
|
|
@@ -37595,13 +37558,8 @@ class ClaudeBaseAdapter {
|
|
|
37595
37558
|
}
|
|
37596
37559
|
return { ...process.env, ...mapped, ...configEnv };
|
|
37597
37560
|
}
|
|
37598
|
-
async
|
|
37599
|
-
|
|
37600
|
-
}
|
|
37601
|
-
async destroy() {
|
|
37602
|
-
return;
|
|
37603
|
-
}
|
|
37604
|
-
async querySDK(transcript, signal) {
|
|
37561
|
+
async* stream(messages, signal) {
|
|
37562
|
+
const transcript = formatTranscript(messages, this.name, this.humanName);
|
|
37605
37563
|
const executableOpt = this.claudeExecutable ? { pathToClaudeCodeExecutable: this.claudeExecutable } : {};
|
|
37606
37564
|
const options = {
|
|
37607
37565
|
cwd: process.cwd(),
|
|
@@ -37615,24 +37573,69 @@ class ClaudeBaseAdapter {
|
|
|
37615
37573
|
...this.sessionId ? { resume: this.sessionId } : {},
|
|
37616
37574
|
...executableOpt
|
|
37617
37575
|
};
|
|
37576
|
+
yield { type: "activity", activity: "thinking" };
|
|
37618
37577
|
try {
|
|
37619
37578
|
for await (const message of query({ prompt: transcript, options })) {
|
|
37620
37579
|
if (signal?.aborted) {
|
|
37621
|
-
|
|
37580
|
+
yield { type: "error", message: `[Aborted] ${this.name} was cancelled` };
|
|
37581
|
+
return;
|
|
37622
37582
|
}
|
|
37623
|
-
if (message
|
|
37583
|
+
if (!message || typeof message !== "object")
|
|
37584
|
+
continue;
|
|
37585
|
+
if ("type" in message && "subtype" in message && "session_id" in message && message.type === "system" && message.subtype === "init" && typeof message.session_id === "string") {
|
|
37624
37586
|
this.sessionId = message.session_id;
|
|
37625
37587
|
}
|
|
37626
|
-
if (message &&
|
|
37588
|
+
if ("type" in message && message.type === "assistant" && "message" in message) {
|
|
37589
|
+
const msg = message.message;
|
|
37590
|
+
const blocks = msg?.content;
|
|
37591
|
+
if (Array.isArray(blocks)) {
|
|
37592
|
+
for (const block of blocks) {
|
|
37593
|
+
if (block.type === "tool_use" && block.name) {
|
|
37594
|
+
const toolName = String(block.name).toLowerCase();
|
|
37595
|
+
if (toolName === "read" || toolName === "glob") {
|
|
37596
|
+
yield { type: "activity", activity: "reading", detail: block.name };
|
|
37597
|
+
} else if (toolName === "write" || toolName === "edit") {
|
|
37598
|
+
yield { type: "activity", activity: "writing", detail: block.name };
|
|
37599
|
+
} else if (toolName === "bash") {
|
|
37600
|
+
yield { type: "activity", activity: "running", detail: "shell" };
|
|
37601
|
+
} else if (toolName === "grep" || toolName === "search" || toolName === "websearch") {
|
|
37602
|
+
yield { type: "activity", activity: "searching", detail: block.name };
|
|
37603
|
+
} else {
|
|
37604
|
+
yield { type: "activity", activity: "thinking", detail: block.name };
|
|
37605
|
+
}
|
|
37606
|
+
} else if (block.type === "thinking") {
|
|
37607
|
+
yield { type: "activity", activity: "thinking" };
|
|
37608
|
+
}
|
|
37609
|
+
}
|
|
37610
|
+
}
|
|
37611
|
+
}
|
|
37612
|
+
if ("type" in message && message.type === "user") {
|
|
37613
|
+
yield { type: "activity", activity: "thinking" };
|
|
37614
|
+
}
|
|
37615
|
+
if ("result" in message) {
|
|
37627
37616
|
const result = message.result;
|
|
37628
|
-
|
|
37617
|
+
const text = typeof result === "string" && result.length > 0 ? result : `[No text response from ${this.name}]`;
|
|
37618
|
+
yield { type: "activity", activity: "idle" };
|
|
37619
|
+
yield { type: "response", text };
|
|
37620
|
+
return;
|
|
37629
37621
|
}
|
|
37630
37622
|
}
|
|
37631
37623
|
} catch (err) {
|
|
37632
37624
|
console.log(`[${this.name}] SDK error:`, err);
|
|
37633
|
-
|
|
37625
|
+
yield { type: "error", message: err instanceof Error ? err.message : String(err) };
|
|
37626
|
+
return;
|
|
37634
37627
|
}
|
|
37635
|
-
|
|
37628
|
+
yield { type: "activity", activity: "idle" };
|
|
37629
|
+
yield { type: "response", text: `[No text response from ${this.name}]` };
|
|
37630
|
+
}
|
|
37631
|
+
async destroy() {
|
|
37632
|
+
return;
|
|
37633
|
+
}
|
|
37634
|
+
getSdkSessionId() {
|
|
37635
|
+
return this.sessionId;
|
|
37636
|
+
}
|
|
37637
|
+
setSdkSessionId(id) {
|
|
37638
|
+
this.sessionId = id;
|
|
37636
37639
|
}
|
|
37637
37640
|
}
|
|
37638
37641
|
|
|
@@ -38082,6 +38085,8 @@ class CodexAdapter {
|
|
|
38082
38085
|
humanName;
|
|
38083
38086
|
codex;
|
|
38084
38087
|
thread;
|
|
38088
|
+
threadId = "";
|
|
38089
|
+
threadOptions = {};
|
|
38085
38090
|
constructor(name, model, humanName) {
|
|
38086
38091
|
this.name = name;
|
|
38087
38092
|
this.model = model;
|
|
@@ -38095,31 +38100,84 @@ class CodexAdapter {
|
|
|
38095
38100
|
...config.env?.OPENAI_API_KEY ? { apiKey: config.env.OPENAI_API_KEY } : {},
|
|
38096
38101
|
...systemPrompt ? { config: { developer_instructions: systemPrompt } } : {}
|
|
38097
38102
|
});
|
|
38098
|
-
this.
|
|
38103
|
+
this.threadOptions = {
|
|
38099
38104
|
model: this.model,
|
|
38100
38105
|
sandboxMode: "danger-full-access",
|
|
38101
38106
|
workingDirectory: process.cwd(),
|
|
38102
38107
|
approvalPolicy: "never",
|
|
38103
38108
|
skipGitRepoCheck: true
|
|
38104
|
-
}
|
|
38109
|
+
};
|
|
38110
|
+
if (this.threadId) {
|
|
38111
|
+
try {
|
|
38112
|
+
this.thread = this.codex.resumeThread(this.threadId, this.threadOptions);
|
|
38113
|
+
return;
|
|
38114
|
+
} catch (err) {
|
|
38115
|
+
console.error(`[${this.name}] resumeThread failed, starting fresh:`, err);
|
|
38116
|
+
this.threadId = "";
|
|
38117
|
+
}
|
|
38118
|
+
}
|
|
38119
|
+
this.thread = this.codex.startThread(this.threadOptions);
|
|
38120
|
+
this.threadId = this.thread.id ?? "";
|
|
38105
38121
|
}
|
|
38106
|
-
async
|
|
38122
|
+
async* stream(messages, signal) {
|
|
38107
38123
|
if (!this.thread) {
|
|
38108
|
-
|
|
38124
|
+
yield { type: "error", message: "[Codex thread not initialized]" };
|
|
38125
|
+
return;
|
|
38109
38126
|
}
|
|
38110
38127
|
if (signal?.aborted) {
|
|
38111
|
-
|
|
38128
|
+
yield { type: "error", message: "[Aborted] Codex was cancelled" };
|
|
38129
|
+
return;
|
|
38112
38130
|
}
|
|
38113
|
-
|
|
38114
|
-
|
|
38115
|
-
|
|
38131
|
+
yield { type: "activity", activity: "thinking" };
|
|
38132
|
+
try {
|
|
38133
|
+
const result = await this.thread.runStreamed(formatTranscript(messages, this.name, this.humanName));
|
|
38134
|
+
let lastAgentMessage = "";
|
|
38135
|
+
for await (const event of result.events) {
|
|
38136
|
+
if (signal?.aborted) {
|
|
38137
|
+
yield { type: "error", message: "[Aborted] Codex was cancelled" };
|
|
38138
|
+
return;
|
|
38139
|
+
}
|
|
38140
|
+
if (event.type === "item.started" || event.type === "item.updated") {
|
|
38141
|
+
const item = event.item;
|
|
38142
|
+
if (item.type === "command_execution") {
|
|
38143
|
+
yield { type: "activity", activity: "running", detail: item.command };
|
|
38144
|
+
} else if (item.type === "file_change") {
|
|
38145
|
+
yield { type: "activity", activity: "writing", detail: "file changes" };
|
|
38146
|
+
} else if (item.type === "reasoning") {
|
|
38147
|
+
yield { type: "activity", activity: "thinking", detail: "reasoning" };
|
|
38148
|
+
} else if (item.type === "web_search") {
|
|
38149
|
+
yield { type: "activity", activity: "searching", detail: item.query };
|
|
38150
|
+
} else if (item.type === "mcp_tool_call") {
|
|
38151
|
+
yield { type: "activity", activity: "running", detail: `${item.server}:${item.tool}` };
|
|
38152
|
+
}
|
|
38153
|
+
}
|
|
38154
|
+
if (event.type === "item.completed") {
|
|
38155
|
+
const item = event.item;
|
|
38156
|
+
if (item.type === "agent_message" && typeof item.text === "string") {
|
|
38157
|
+
lastAgentMessage = item.text;
|
|
38158
|
+
}
|
|
38159
|
+
}
|
|
38160
|
+
}
|
|
38161
|
+
const text = lastAgentMessage.length > 0 ? lastAgentMessage : `[No text response from ${this.name}]`;
|
|
38162
|
+
if (!this.threadId && this.thread?.id) {
|
|
38163
|
+
this.threadId = this.thread.id;
|
|
38164
|
+
}
|
|
38165
|
+
yield { type: "activity", activity: "idle" };
|
|
38166
|
+
yield { type: "response", text };
|
|
38167
|
+
} catch (err) {
|
|
38168
|
+
yield { type: "error", message: err instanceof Error ? err.message : String(err) };
|
|
38116
38169
|
}
|
|
38117
|
-
return "[No text response from Codex]";
|
|
38118
38170
|
}
|
|
38119
38171
|
async destroy() {
|
|
38120
38172
|
this.thread = undefined;
|
|
38121
38173
|
this.codex = undefined;
|
|
38122
38174
|
}
|
|
38175
|
+
getSdkSessionId() {
|
|
38176
|
+
return this.threadId;
|
|
38177
|
+
}
|
|
38178
|
+
setSdkSessionId(id) {
|
|
38179
|
+
this.threadId = id;
|
|
38180
|
+
}
|
|
38123
38181
|
}
|
|
38124
38182
|
|
|
38125
38183
|
// node_modules/@github/copilot-sdk/dist/client.js
|
|
@@ -39302,6 +39360,7 @@ class CopilotAdapter {
|
|
|
39302
39360
|
systemPrompt = "";
|
|
39303
39361
|
cliPath;
|
|
39304
39362
|
timeout = 600000;
|
|
39363
|
+
copilotSessionId = "";
|
|
39305
39364
|
constructor(name, model, humanName) {
|
|
39306
39365
|
this.name = name;
|
|
39307
39366
|
this.model = model;
|
|
@@ -39315,64 +39374,180 @@ class CopilotAdapter {
|
|
|
39315
39374
|
}
|
|
39316
39375
|
await this.createSession();
|
|
39317
39376
|
}
|
|
39318
|
-
async
|
|
39377
|
+
async* stream(messages, signal) {
|
|
39319
39378
|
if (!this.session) {
|
|
39320
|
-
|
|
39379
|
+
yield { type: "error", message: "[Copilot session not initialized]" };
|
|
39380
|
+
return;
|
|
39321
39381
|
}
|
|
39322
39382
|
if (signal?.aborted) {
|
|
39323
|
-
|
|
39383
|
+
yield { type: "error", message: "[Aborted] Copilot was cancelled" };
|
|
39384
|
+
return;
|
|
39324
39385
|
}
|
|
39386
|
+
yield { type: "activity", activity: "thinking" };
|
|
39325
39387
|
const transcript = formatTranscript(messages, this.name, this.humanName);
|
|
39388
|
+
const eventQueue = [];
|
|
39389
|
+
let resolve4 = null;
|
|
39390
|
+
let done = false;
|
|
39391
|
+
const push = (event) => {
|
|
39392
|
+
eventQueue.push(event);
|
|
39393
|
+
if (resolve4) {
|
|
39394
|
+
resolve4();
|
|
39395
|
+
resolve4 = null;
|
|
39396
|
+
}
|
|
39397
|
+
};
|
|
39398
|
+
const waitForEvent = () => {
|
|
39399
|
+
if (eventQueue.length > 0 || done)
|
|
39400
|
+
return Promise.resolve();
|
|
39401
|
+
return new Promise((r) => {
|
|
39402
|
+
resolve4 = r;
|
|
39403
|
+
});
|
|
39404
|
+
};
|
|
39405
|
+
const timer = setTimeout(() => {
|
|
39406
|
+
push({ type: "error", message: `[Timeout] ${this.name} exceeded ${Math.floor(this.timeout / 1000)}s` });
|
|
39407
|
+
done = true;
|
|
39408
|
+
}, this.timeout);
|
|
39409
|
+
const unsubscribe = this.session.on((event) => {
|
|
39410
|
+
if (signal?.aborted) {
|
|
39411
|
+
push({ type: "error", message: `[Aborted] ${this.name} was cancelled` });
|
|
39412
|
+
done = true;
|
|
39413
|
+
return;
|
|
39414
|
+
}
|
|
39415
|
+
if (event.type === "tool.execution_start") {
|
|
39416
|
+
const toolName = String(event.data?.toolName ?? "").toLowerCase();
|
|
39417
|
+
if (toolName === "view" || toolName === "read" || toolName === "report_intent") {
|
|
39418
|
+
push({ type: "activity", activity: "reading", detail: event.data?.toolName });
|
|
39419
|
+
} else if (toolName === "create" || toolName === "edit" || toolName === "write") {
|
|
39420
|
+
push({ type: "activity", activity: "writing", detail: event.data?.toolName });
|
|
39421
|
+
} else if (toolName === "run" || toolName === "bash" || toolName === "shell") {
|
|
39422
|
+
push({ type: "activity", activity: "running", detail: event.data?.toolName });
|
|
39423
|
+
} else if (toolName === "search" || toolName === "grep" || toolName === "find") {
|
|
39424
|
+
push({ type: "activity", activity: "searching", detail: event.data?.toolName });
|
|
39425
|
+
} else {
|
|
39426
|
+
push({ type: "activity", activity: "thinking", detail: event.data?.toolName });
|
|
39427
|
+
}
|
|
39428
|
+
}
|
|
39429
|
+
if (event.type === "tool.execution_complete") {
|
|
39430
|
+
push({ type: "activity", activity: "thinking" });
|
|
39431
|
+
}
|
|
39432
|
+
if (event.type === "assistant.turn_start") {
|
|
39433
|
+
push({ type: "activity", activity: "thinking" });
|
|
39434
|
+
}
|
|
39435
|
+
if (event.type === "assistant.message") {
|
|
39436
|
+
const content = event.data?.content;
|
|
39437
|
+
if (typeof content === "string" && content.length > 0) {
|
|
39438
|
+
push({ type: "activity", activity: "idle" });
|
|
39439
|
+
push({ type: "response", text: content });
|
|
39440
|
+
done = true;
|
|
39441
|
+
}
|
|
39442
|
+
}
|
|
39443
|
+
if (event.type === "session.error") {
|
|
39444
|
+
push({ type: "error", message: event.data?.message ?? "Unknown Copilot error" });
|
|
39445
|
+
done = true;
|
|
39446
|
+
}
|
|
39447
|
+
});
|
|
39448
|
+
const sendSession = async () => {
|
|
39449
|
+
try {
|
|
39450
|
+
await this.session.send({ prompt: transcript });
|
|
39451
|
+
} catch (err) {
|
|
39452
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
39453
|
+
if (message.includes("Session not found")) {
|
|
39454
|
+
await this.createSession();
|
|
39455
|
+
try {
|
|
39456
|
+
await this.session.send({ prompt: transcript });
|
|
39457
|
+
} catch (retryErr) {
|
|
39458
|
+
push({ type: "error", message: retryErr instanceof Error ? retryErr.message : String(retryErr) });
|
|
39459
|
+
done = true;
|
|
39460
|
+
}
|
|
39461
|
+
} else {
|
|
39462
|
+
push({ type: "error", message });
|
|
39463
|
+
done = true;
|
|
39464
|
+
}
|
|
39465
|
+
}
|
|
39466
|
+
};
|
|
39467
|
+
sendSession();
|
|
39326
39468
|
try {
|
|
39327
|
-
|
|
39328
|
-
|
|
39329
|
-
|
|
39330
|
-
|
|
39331
|
-
|
|
39332
|
-
|
|
39469
|
+
while (!done || eventQueue.length > 0) {
|
|
39470
|
+
await waitForEvent();
|
|
39471
|
+
while (eventQueue.length > 0) {
|
|
39472
|
+
const event = eventQueue.shift();
|
|
39473
|
+
yield event;
|
|
39474
|
+
if (event.type === "response" || event.type === "error") {
|
|
39475
|
+
clearTimeout(timer);
|
|
39476
|
+
unsubscribe?.();
|
|
39477
|
+
return;
|
|
39478
|
+
}
|
|
39479
|
+
}
|
|
39333
39480
|
}
|
|
39334
|
-
|
|
39481
|
+
} finally {
|
|
39482
|
+
clearTimeout(timer);
|
|
39483
|
+
unsubscribe?.();
|
|
39335
39484
|
}
|
|
39485
|
+
yield { type: "activity", activity: "idle" };
|
|
39486
|
+
yield { type: "response", text: `[No text response from ${this.name}]` };
|
|
39336
39487
|
}
|
|
39337
39488
|
async destroy() {
|
|
39338
39489
|
if (this.session) {
|
|
39339
|
-
|
|
39490
|
+
try {
|
|
39491
|
+
await this.session.disconnect();
|
|
39492
|
+
} catch (err) {
|
|
39493
|
+
console.error(`[${this.name}] disconnect:`, err);
|
|
39494
|
+
}
|
|
39340
39495
|
}
|
|
39341
39496
|
if (this.client) {
|
|
39342
|
-
|
|
39497
|
+
try {
|
|
39498
|
+
await this.client.stop();
|
|
39499
|
+
} catch (err) {
|
|
39500
|
+
console.error(`[${this.name}] stop:`, err);
|
|
39501
|
+
}
|
|
39343
39502
|
}
|
|
39344
39503
|
}
|
|
39504
|
+
getSdkSessionId() {
|
|
39505
|
+
return this.copilotSessionId;
|
|
39506
|
+
}
|
|
39507
|
+
setSdkSessionId(id) {
|
|
39508
|
+
this.copilotSessionId = id;
|
|
39509
|
+
}
|
|
39345
39510
|
async createSession() {
|
|
39346
39511
|
if (this.session) {
|
|
39347
39512
|
try {
|
|
39348
39513
|
await this.session.disconnect();
|
|
39349
|
-
} catch {
|
|
39514
|
+
} catch (err) {
|
|
39515
|
+
console.error(`[${this.name}] stale session disconnect:`, err);
|
|
39516
|
+
}
|
|
39350
39517
|
}
|
|
39351
39518
|
if (this.client) {
|
|
39352
39519
|
try {
|
|
39353
39520
|
await this.client.stop();
|
|
39354
|
-
} catch {
|
|
39521
|
+
} catch (err) {
|
|
39522
|
+
console.error(`[${this.name}] stale client stop:`, err);
|
|
39523
|
+
}
|
|
39355
39524
|
}
|
|
39356
39525
|
process.env.NODE_NO_WARNINGS = "1";
|
|
39357
39526
|
this.client = new CopilotClient({
|
|
39358
39527
|
...this.cliPath ? { cliPath: this.cliPath } : {}
|
|
39359
39528
|
});
|
|
39360
39529
|
await this.client.start();
|
|
39530
|
+
if (this.copilotSessionId) {
|
|
39531
|
+
try {
|
|
39532
|
+
this.session = await this.client.resumeSession(this.copilotSessionId, {
|
|
39533
|
+
model: this.model,
|
|
39534
|
+
systemMessage: { content: this.systemPrompt },
|
|
39535
|
+
onPermissionRequest: approveAll
|
|
39536
|
+
});
|
|
39537
|
+
return;
|
|
39538
|
+
} catch (err) {
|
|
39539
|
+
console.error(`[${this.name}] resumeSession failed, creating new:`, err);
|
|
39540
|
+
this.copilotSessionId = "";
|
|
39541
|
+
}
|
|
39542
|
+
}
|
|
39543
|
+
const sessionId = `llm-party-${this.name}-${Date.now()}`;
|
|
39361
39544
|
this.session = await this.client.createSession({
|
|
39545
|
+
sessionId,
|
|
39362
39546
|
model: this.model,
|
|
39363
39547
|
systemMessage: { content: this.systemPrompt },
|
|
39364
39548
|
onPermissionRequest: approveAll
|
|
39365
39549
|
});
|
|
39366
|
-
|
|
39367
|
-
async sendToSession(transcript) {
|
|
39368
|
-
if (!this.session) {
|
|
39369
|
-
return "[Copilot session not initialized]";
|
|
39370
|
-
}
|
|
39371
|
-
const response = await this.session.sendAndWait({ prompt: transcript }, this.timeout);
|
|
39372
|
-
if (response && response.data && typeof response.data.content === "string" && response.data.content.length > 0) {
|
|
39373
|
-
return response.data.content;
|
|
39374
|
-
}
|
|
39375
|
-
return "[No text response from Copilot]";
|
|
39550
|
+
this.copilotSessionId = sessionId;
|
|
39376
39551
|
}
|
|
39377
39552
|
}
|
|
39378
39553
|
|
|
@@ -39629,7 +39804,7 @@ async function loadConfig2(configPath) {
|
|
|
39629
39804
|
}
|
|
39630
39805
|
|
|
39631
39806
|
// src/orchestrator.ts
|
|
39632
|
-
import { appendFile, mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
|
|
39807
|
+
import { appendFile, mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
39633
39808
|
import { randomBytes } from "crypto";
|
|
39634
39809
|
import path9 from "path";
|
|
39635
39810
|
|
|
@@ -39654,6 +39829,88 @@ var DEFAULT_REMINDERS = [
|
|
|
39654
39829
|
"Self-memory check: did you receive a correction this session? Write it to your agent file now.",
|
|
39655
39830
|
"Global awareness: if this work affects other projects, write a one-liner to projects.yml history."
|
|
39656
39831
|
];
|
|
39832
|
+
var QUEUE_TTL_MS = 5 * 60 * 1000;
|
|
39833
|
+
var MAX_QUEUE_SIZE = 20;
|
|
39834
|
+
|
|
39835
|
+
class AgentQueueManager {
|
|
39836
|
+
queues = new Map;
|
|
39837
|
+
register(agentName) {
|
|
39838
|
+
this.queues.set(agentName, { processing: false, pending: [] });
|
|
39839
|
+
}
|
|
39840
|
+
enqueue(agentName, message, maxSize = MAX_QUEUE_SIZE) {
|
|
39841
|
+
const queue = this.queues.get(agentName);
|
|
39842
|
+
if (!queue)
|
|
39843
|
+
return false;
|
|
39844
|
+
if (queue.pending.length >= maxSize) {
|
|
39845
|
+
queue.pending.shift();
|
|
39846
|
+
}
|
|
39847
|
+
queue.pending.push(message);
|
|
39848
|
+
return true;
|
|
39849
|
+
}
|
|
39850
|
+
drain(agentName, ttlMs = QUEUE_TTL_MS) {
|
|
39851
|
+
const queue = this.queues.get(agentName);
|
|
39852
|
+
if (!queue)
|
|
39853
|
+
return [];
|
|
39854
|
+
const now = Date.now();
|
|
39855
|
+
const valid = queue.pending.filter((m2) => now - new Date(m2.queuedAt).getTime() < ttlMs);
|
|
39856
|
+
queue.pending = [];
|
|
39857
|
+
return valid;
|
|
39858
|
+
}
|
|
39859
|
+
isProcessing(agentName) {
|
|
39860
|
+
return this.queues.get(agentName)?.processing ?? false;
|
|
39861
|
+
}
|
|
39862
|
+
setProcessing(agentName, value) {
|
|
39863
|
+
const queue = this.queues.get(agentName);
|
|
39864
|
+
if (queue)
|
|
39865
|
+
queue.processing = value;
|
|
39866
|
+
}
|
|
39867
|
+
hasPending(agentName) {
|
|
39868
|
+
return (this.queues.get(agentName)?.pending.length ?? 0) > 0;
|
|
39869
|
+
}
|
|
39870
|
+
pendingCount(agentName) {
|
|
39871
|
+
return this.queues.get(agentName)?.pending.length ?? 0;
|
|
39872
|
+
}
|
|
39873
|
+
get anyProcessing() {
|
|
39874
|
+
for (const q2 of this.queues.values()) {
|
|
39875
|
+
if (q2.processing)
|
|
39876
|
+
return true;
|
|
39877
|
+
}
|
|
39878
|
+
return false;
|
|
39879
|
+
}
|
|
39880
|
+
setController(agentName, controller) {
|
|
39881
|
+
const queue = this.queues.get(agentName);
|
|
39882
|
+
if (queue)
|
|
39883
|
+
queue.controller = controller;
|
|
39884
|
+
}
|
|
39885
|
+
cancelled = new Set;
|
|
39886
|
+
abortAgent(agentName) {
|
|
39887
|
+
const queue = this.queues.get(agentName);
|
|
39888
|
+
if (!queue)
|
|
39889
|
+
return;
|
|
39890
|
+
this.cancelled.add(agentName);
|
|
39891
|
+
queue.controller?.abort();
|
|
39892
|
+
queue.pending = [];
|
|
39893
|
+
queue.processing = false;
|
|
39894
|
+
}
|
|
39895
|
+
wasCancelled(agentName) {
|
|
39896
|
+
return this.cancelled.has(agentName);
|
|
39897
|
+
}
|
|
39898
|
+
clearCancelled(agentName) {
|
|
39899
|
+
this.cancelled.delete(agentName);
|
|
39900
|
+
}
|
|
39901
|
+
abortAll() {
|
|
39902
|
+
for (const q2 of this.queues.values()) {
|
|
39903
|
+
q2.controller?.abort();
|
|
39904
|
+
q2.pending = [];
|
|
39905
|
+
}
|
|
39906
|
+
}
|
|
39907
|
+
clearAll() {
|
|
39908
|
+
for (const q2 of this.queues.values()) {
|
|
39909
|
+
q2.pending = [];
|
|
39910
|
+
q2.processing = false;
|
|
39911
|
+
}
|
|
39912
|
+
}
|
|
39913
|
+
}
|
|
39657
39914
|
|
|
39658
39915
|
class Orchestrator {
|
|
39659
39916
|
agents;
|
|
@@ -39669,7 +39926,16 @@ class Orchestrator {
|
|
|
39669
39926
|
contextWindowSize;
|
|
39670
39927
|
reminderInterval;
|
|
39671
39928
|
reminderCursors = new Map;
|
|
39929
|
+
maxAutoHops;
|
|
39930
|
+
queueTtlMs;
|
|
39931
|
+
maxQueueSize;
|
|
39672
39932
|
messageId = 0;
|
|
39933
|
+
stickyTargets;
|
|
39934
|
+
queueManager = new AgentQueueManager;
|
|
39935
|
+
manifestSavePromise = Promise.resolve();
|
|
39936
|
+
onMessage = () => {};
|
|
39937
|
+
onActivity = () => {};
|
|
39938
|
+
onSystem = () => {};
|
|
39673
39939
|
constructor(agents, humanName = "USER", agentTags, humanTag, defaultTimeout = 600000, agentTimeouts, options) {
|
|
39674
39940
|
this.agents = new Map(agents.map((agent) => [agent.name, agent]));
|
|
39675
39941
|
this.agentTags = new Map(agents.map((agent) => [agent.name, agentTags?.[agent.name] ?? toTag(agent.name)]));
|
|
@@ -39679,12 +39945,21 @@ class Orchestrator {
|
|
|
39679
39945
|
this.agentTimeouts = new Map(Object.entries(agentTimeouts ?? {}));
|
|
39680
39946
|
this.contextWindowSize = options?.contextWindowSize ?? 16;
|
|
39681
39947
|
this.reminderInterval = options?.reminderInterval ?? 8;
|
|
39948
|
+
this.maxAutoHops = options?.maxAutoHops ?? 15;
|
|
39949
|
+
this.queueTtlMs = options?.queueTtlMs ?? QUEUE_TTL_MS;
|
|
39950
|
+
this.maxQueueSize = options?.maxQueueSize ?? MAX_QUEUE_SIZE;
|
|
39682
39951
|
this.sessionId = createSessionId();
|
|
39683
39952
|
this.transcriptPath = path9.resolve(".llm-party", "sessions", `transcript-${this.sessionId}.jsonl`);
|
|
39684
39953
|
for (const agent of agents) {
|
|
39685
39954
|
this.lastSeenByAgent.set(agent.name, 0);
|
|
39955
|
+
this.queueManager.register(agent.name);
|
|
39686
39956
|
}
|
|
39687
39957
|
}
|
|
39958
|
+
setCallbacks(onMessage, onActivity, onSystem) {
|
|
39959
|
+
this.onMessage = onMessage;
|
|
39960
|
+
this.onActivity = onActivity;
|
|
39961
|
+
this.onSystem = onSystem;
|
|
39962
|
+
}
|
|
39688
39963
|
getSessionId() {
|
|
39689
39964
|
return this.sessionId;
|
|
39690
39965
|
}
|
|
@@ -39697,12 +39972,29 @@ class Orchestrator {
|
|
|
39697
39972
|
getHumanTag() {
|
|
39698
39973
|
return this.humanTag;
|
|
39699
39974
|
}
|
|
39975
|
+
get dispatching() {
|
|
39976
|
+
return this.queueManager.anyProcessing;
|
|
39977
|
+
}
|
|
39978
|
+
getStickyTarget() {
|
|
39979
|
+
return this.stickyTargets;
|
|
39980
|
+
}
|
|
39981
|
+
setStickyTarget(targets) {
|
|
39982
|
+
this.stickyTargets = targets;
|
|
39983
|
+
}
|
|
39984
|
+
getQueueStatus() {
|
|
39985
|
+
return this.listAgents().map((a) => ({
|
|
39986
|
+
name: a.name,
|
|
39987
|
+
processing: this.queueManager.isProcessing(a.name),
|
|
39988
|
+
pending: this.queueManager.pendingCount(a.name)
|
|
39989
|
+
}));
|
|
39990
|
+
}
|
|
39700
39991
|
clearConversation() {
|
|
39701
39992
|
this.conversation.length = 0;
|
|
39702
39993
|
this.messageId = 0;
|
|
39703
39994
|
for (const agent of this.agents.keys()) {
|
|
39704
39995
|
this.lastSeenByAgent.set(agent, 0);
|
|
39705
39996
|
}
|
|
39997
|
+
this.queueManager.clearAll();
|
|
39706
39998
|
this.sessionId = createSessionId();
|
|
39707
39999
|
this.transcriptPath = path9.resolve(".llm-party", "sessions", `transcript-${this.sessionId}.jsonl`);
|
|
39708
40000
|
}
|
|
@@ -39739,62 +40031,165 @@ class Orchestrator {
|
|
|
39739
40031
|
const tag = this.agentTags.get(agent.name) ?? toTag(agent.name);
|
|
39740
40032
|
return agent.name.toLowerCase() === normalized || tag.toLowerCase() === normalized;
|
|
39741
40033
|
}).map((agent) => agent.name);
|
|
39742
|
-
if (byName.length > 0)
|
|
40034
|
+
if (byName.length > 0)
|
|
39743
40035
|
return byName;
|
|
39744
|
-
}
|
|
39745
40036
|
return Array.from(this.agents.values()).filter((agent) => agent.provider.toLowerCase() === normalized).map((agent) => agent.name);
|
|
39746
40037
|
}
|
|
39747
|
-
|
|
39748
|
-
|
|
39749
|
-
|
|
39750
|
-
|
|
39751
|
-
const requestedTargets = targetAgentNames && targetAgentNames.length > 0 ? targetAgentNames : Array.from(this.agents.keys());
|
|
39752
|
-
const targets = requestedTargets.map((name) => this.agents.get(name)).filter((agent) => Boolean(agent));
|
|
39753
|
-
const historyMaxId = this.messageId;
|
|
39754
|
-
const settled = await Promise.allSettled(targets.map(async (agent) => {
|
|
39755
|
-
const lastSeen = this.lastSeenByAgent.get(agent.name) ?? 0;
|
|
39756
|
-
const unseen = this.conversation.filter((msg) => msg.id > lastSeen && msg.from.toUpperCase() !== agent.name.toUpperCase());
|
|
39757
|
-
if (unseen.length === 0) {
|
|
39758
|
-
this.lastSeenByAgent.set(agent.name, historyMaxId);
|
|
39759
|
-
return null;
|
|
39760
|
-
}
|
|
39761
|
-
const inputMessages = this.buildInputForAgent(agent.name, unseen);
|
|
39762
|
-
const responseText = await this.sendWithTimeout(agent, inputMessages, this.timeoutFor(agent.name));
|
|
39763
|
-
const response = {
|
|
39764
|
-
id: ++this.messageId,
|
|
39765
|
-
from: agent.name.toUpperCase(),
|
|
39766
|
-
text: responseText,
|
|
39767
|
-
createdAt: new Date().toISOString()
|
|
39768
|
-
};
|
|
39769
|
-
this.lastSeenByAgent.set(agent.name, historyMaxId);
|
|
39770
|
-
this.conversation.push(response);
|
|
39771
|
-
await this.appendTranscript(response);
|
|
39772
|
-
onMessage(response);
|
|
39773
|
-
return response;
|
|
39774
|
-
}));
|
|
39775
|
-
const results = [];
|
|
39776
|
-
for (let idx = 0;idx < settled.length; idx++) {
|
|
39777
|
-
const item = settled[idx];
|
|
39778
|
-
if (item.status === "fulfilled") {
|
|
39779
|
-
if (item.value) {
|
|
39780
|
-
results.push(item.value);
|
|
39781
|
-
}
|
|
40038
|
+
dispatchToTargets(targetAgentNames, chainHops = 0) {
|
|
40039
|
+
for (const name of targetAgentNames) {
|
|
40040
|
+
const agent = this.agents.get(name);
|
|
40041
|
+
if (!agent)
|
|
39782
40042
|
continue;
|
|
40043
|
+
if (this.queueManager.isProcessing(name)) {
|
|
40044
|
+
this.queueManager.enqueue(name, {
|
|
40045
|
+
from: "dispatch",
|
|
40046
|
+
text: "",
|
|
40047
|
+
queuedAt: new Date().toISOString(),
|
|
40048
|
+
chainHops
|
|
40049
|
+
}, this.maxQueueSize);
|
|
40050
|
+
this.onSystem(`Queued for ${name} (busy, ${this.queueManager.pendingCount(name)} pending)`);
|
|
40051
|
+
} else {
|
|
40052
|
+
this.processAgent(name, chainHops);
|
|
39783
40053
|
}
|
|
39784
|
-
const agent = targets[idx];
|
|
39785
|
-
const response = {
|
|
39786
|
-
id: ++this.messageId,
|
|
39787
|
-
from: agent.name.toUpperCase(),
|
|
39788
|
-
text: `[Adapter Error] ${item.reason instanceof Error ? item.reason.message : String(item.reason)}`,
|
|
39789
|
-
createdAt: new Date().toISOString()
|
|
39790
|
-
};
|
|
39791
|
-
this.lastSeenByAgent.set(agent.name, historyMaxId);
|
|
39792
|
-
this.conversation.push(response);
|
|
39793
|
-
await this.appendTranscript(response);
|
|
39794
|
-
onMessage(response);
|
|
39795
|
-
results.push(response);
|
|
39796
40054
|
}
|
|
39797
|
-
|
|
40055
|
+
}
|
|
40056
|
+
async processAgent(agentName, chainHops) {
|
|
40057
|
+
const agent = this.agents.get(agentName);
|
|
40058
|
+
if (!agent)
|
|
40059
|
+
return;
|
|
40060
|
+
this.queueManager.clearCancelled(agentName);
|
|
40061
|
+
this.queueManager.setProcessing(agentName, true);
|
|
40062
|
+
this.onActivity(agentName, "thinking");
|
|
40063
|
+
const historyMaxId = this.messageId;
|
|
40064
|
+
const lastSeen = this.lastSeenByAgent.get(agentName) ?? 0;
|
|
40065
|
+
const unseen = this.conversation.filter((msg) => msg.id > lastSeen && msg.from.toUpperCase() !== agentName.toUpperCase());
|
|
40066
|
+
if (unseen.length === 0) {
|
|
40067
|
+
this.lastSeenByAgent.set(agentName, historyMaxId);
|
|
40068
|
+
this.queueManager.setProcessing(agentName, false);
|
|
40069
|
+
this.onActivity(agentName, "idle");
|
|
40070
|
+
this.drainQueue(agentName);
|
|
40071
|
+
return;
|
|
40072
|
+
}
|
|
40073
|
+
const inputMessages = this.buildInputForAgent(agentName, unseen);
|
|
40074
|
+
const responseText = await this.streamWithTimeout(agentName, agent, inputMessages, this.timeoutFor(agentName));
|
|
40075
|
+
if (this.queueManager.wasCancelled(agentName)) {
|
|
40076
|
+
this.lastSeenByAgent.set(agentName, historyMaxId);
|
|
40077
|
+
this.queueManager.setProcessing(agentName, false);
|
|
40078
|
+
this.onActivity(agentName, "idle");
|
|
40079
|
+
return;
|
|
40080
|
+
}
|
|
40081
|
+
const response = {
|
|
40082
|
+
id: ++this.messageId,
|
|
40083
|
+
from: agentName.toUpperCase(),
|
|
40084
|
+
text: responseText,
|
|
40085
|
+
createdAt: new Date().toISOString()
|
|
40086
|
+
};
|
|
40087
|
+
this.lastSeenByAgent.set(agentName, historyMaxId);
|
|
40088
|
+
this.conversation.push(response);
|
|
40089
|
+
await this.appendTranscript(response);
|
|
40090
|
+
this.onMessage(response);
|
|
40091
|
+
await this.saveManifest();
|
|
40092
|
+
this.queueManager.setProcessing(agentName, false);
|
|
40093
|
+
const isError = responseText.startsWith("[Timeout]") || responseText.startsWith("[Error]") || responseText.startsWith("[Adapter Error]");
|
|
40094
|
+
if (!isError) {
|
|
40095
|
+
this.processHandoffs(response, chainHops);
|
|
40096
|
+
}
|
|
40097
|
+
this.drainQueue(agentName);
|
|
40098
|
+
}
|
|
40099
|
+
processHandoffs(response, currentHops) {
|
|
40100
|
+
const selectors = extractNextSelectors([response]);
|
|
40101
|
+
if (selectors.length === 0)
|
|
40102
|
+
return;
|
|
40103
|
+
const humanTag = this.humanTag.toLowerCase();
|
|
40104
|
+
const humanName = this.humanName.toLowerCase();
|
|
40105
|
+
const agentSelectors = selectors.filter((s) => {
|
|
40106
|
+
const n = s.toLowerCase();
|
|
40107
|
+
return n !== humanTag && n !== humanName;
|
|
40108
|
+
});
|
|
40109
|
+
if (agentSelectors.length === 0)
|
|
40110
|
+
return;
|
|
40111
|
+
const resolvedTargets = Array.from(new Set(agentSelectors.flatMap((s) => this.resolveTargets(s))));
|
|
40112
|
+
if (resolvedTargets.length === 0)
|
|
40113
|
+
return;
|
|
40114
|
+
const nextHops = currentHops + 1;
|
|
40115
|
+
if (nextHops >= this.maxAutoHops) {
|
|
40116
|
+
this.onSystem(`Stopped auto-handoff after ${this.maxAutoHops} hops.`);
|
|
40117
|
+
return;
|
|
40118
|
+
}
|
|
40119
|
+
this.onSystem(`Auto handoff via @next to ${resolvedTargets.join(", ")}`);
|
|
40120
|
+
this.dispatchToTargets(resolvedTargets, nextHops);
|
|
40121
|
+
}
|
|
40122
|
+
drainQueue(agentName) {
|
|
40123
|
+
if (!this.queueManager.hasPending(agentName)) {
|
|
40124
|
+
this.onActivity(agentName, "idle");
|
|
40125
|
+
return;
|
|
40126
|
+
}
|
|
40127
|
+
const pending = this.queueManager.drain(agentName, this.queueTtlMs);
|
|
40128
|
+
if (pending.length === 0) {
|
|
40129
|
+
this.onActivity(agentName, "idle");
|
|
40130
|
+
return;
|
|
40131
|
+
}
|
|
40132
|
+
const maxHops = Math.max(...pending.map((m2) => m2.chainHops));
|
|
40133
|
+
if (maxHops >= this.maxAutoHops) {
|
|
40134
|
+
this.onSystem(`Stopped auto-handoff for ${agentName} after ${this.maxAutoHops} hops.`);
|
|
40135
|
+
this.onActivity(agentName, "idle");
|
|
40136
|
+
return;
|
|
40137
|
+
}
|
|
40138
|
+
this.processAgent(agentName, maxHops);
|
|
40139
|
+
}
|
|
40140
|
+
async streamWithTimeout(agentName, agent, messages, timeoutMs) {
|
|
40141
|
+
const controller = new AbortController;
|
|
40142
|
+
this.queueManager.setController(agentName, controller);
|
|
40143
|
+
let timer;
|
|
40144
|
+
let resolved = false;
|
|
40145
|
+
return new Promise((resolve4) => {
|
|
40146
|
+
timer = setTimeout(() => {
|
|
40147
|
+
if (!resolved) {
|
|
40148
|
+
resolved = true;
|
|
40149
|
+
controller.abort();
|
|
40150
|
+
this.onActivity(agentName, "error", "timeout");
|
|
40151
|
+
resolve4(`[Timeout] ${agentName} exceeded ${Math.floor(timeoutMs / 1000)}s`);
|
|
40152
|
+
}
|
|
40153
|
+
}, timeoutMs);
|
|
40154
|
+
(async () => {
|
|
40155
|
+
try {
|
|
40156
|
+
for await (const event of agent.stream(messages, controller.signal)) {
|
|
40157
|
+
if (resolved)
|
|
40158
|
+
return;
|
|
40159
|
+
if (event.type === "activity") {
|
|
40160
|
+
this.onActivity(agentName, event.activity, event.detail);
|
|
40161
|
+
} else if (event.type === "response") {
|
|
40162
|
+
resolved = true;
|
|
40163
|
+
if (timer)
|
|
40164
|
+
clearTimeout(timer);
|
|
40165
|
+
resolve4(event.text);
|
|
40166
|
+
return;
|
|
40167
|
+
} else if (event.type === "error") {
|
|
40168
|
+
resolved = true;
|
|
40169
|
+
if (timer)
|
|
40170
|
+
clearTimeout(timer);
|
|
40171
|
+
this.onActivity(agentName, "error");
|
|
40172
|
+
resolve4(`[Error] ${agentName}: ${event.message}`);
|
|
40173
|
+
return;
|
|
40174
|
+
}
|
|
40175
|
+
}
|
|
40176
|
+
if (!resolved) {
|
|
40177
|
+
resolved = true;
|
|
40178
|
+
if (timer)
|
|
40179
|
+
clearTimeout(timer);
|
|
40180
|
+
resolve4(`[No text response from ${agentName}]`);
|
|
40181
|
+
}
|
|
40182
|
+
} catch (err) {
|
|
40183
|
+
if (!resolved) {
|
|
40184
|
+
resolved = true;
|
|
40185
|
+
if (timer)
|
|
40186
|
+
clearTimeout(timer);
|
|
40187
|
+
this.onActivity(agentName, "error");
|
|
40188
|
+
resolve4(`[Error] ${agentName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
40189
|
+
}
|
|
40190
|
+
}
|
|
40191
|
+
})();
|
|
40192
|
+
});
|
|
39798
40193
|
}
|
|
39799
40194
|
async appendTranscript(message) {
|
|
39800
40195
|
try {
|
|
@@ -39807,23 +40202,91 @@ class Orchestrator {
|
|
|
39807
40202
|
async saveHistory(targetPath) {
|
|
39808
40203
|
await writeFile5(targetPath, JSON.stringify(this.conversation, null, 2), "utf8");
|
|
39809
40204
|
}
|
|
39810
|
-
async
|
|
39811
|
-
const
|
|
39812
|
-
|
|
39813
|
-
const
|
|
39814
|
-
|
|
39815
|
-
|
|
39816
|
-
|
|
39817
|
-
|
|
40205
|
+
async loadTranscript(sessionId) {
|
|
40206
|
+
const transcriptFile = path9.resolve(".llm-party", "sessions", `transcript-${sessionId}.jsonl`);
|
|
40207
|
+
const content = await readFile5(transcriptFile, "utf8");
|
|
40208
|
+
const lines = content.trim().split(`
|
|
40209
|
+
`).filter(Boolean);
|
|
40210
|
+
const messages = lines.map((line) => JSON.parse(line));
|
|
40211
|
+
this.conversation.length = 0;
|
|
40212
|
+
this.conversation.push(...messages);
|
|
40213
|
+
const maxId = messages.length > 0 ? Math.max(...messages.map((m2) => m2.id)) : 0;
|
|
40214
|
+
this.messageId = maxId;
|
|
40215
|
+
for (const agent of this.agents.keys()) {
|
|
40216
|
+
this.lastSeenByAgent.set(agent, maxId);
|
|
40217
|
+
}
|
|
40218
|
+
this.sessionId = sessionId;
|
|
40219
|
+
this.transcriptPath = transcriptFile;
|
|
40220
|
+
await this.loadManifest();
|
|
40221
|
+
return messages;
|
|
40222
|
+
}
|
|
40223
|
+
hasMessages() {
|
|
40224
|
+
return this.conversation.length > 0;
|
|
40225
|
+
}
|
|
40226
|
+
manifestPath() {
|
|
40227
|
+
const dir = path9.dirname(this.transcriptPath);
|
|
40228
|
+
const base = path9.basename(this.transcriptPath, ".jsonl");
|
|
40229
|
+
return path9.join(dir, `${base}.manifest.json`);
|
|
40230
|
+
}
|
|
40231
|
+
async saveManifest() {
|
|
40232
|
+
this.manifestSavePromise = this.manifestSavePromise.then(async () => {
|
|
40233
|
+
try {
|
|
40234
|
+
const agents = {};
|
|
40235
|
+
for (const [name, adapter] of this.agents) {
|
|
40236
|
+
const sid = adapter.getSdkSessionId();
|
|
40237
|
+
agents[name] = {
|
|
40238
|
+
provider: adapter.provider,
|
|
40239
|
+
sdkSessionId: sid || "",
|
|
40240
|
+
lastSeenId: this.lastSeenByAgent.get(name) ?? 0
|
|
40241
|
+
};
|
|
40242
|
+
}
|
|
40243
|
+
const manifest = {
|
|
40244
|
+
orchestratorSessionId: this.sessionId,
|
|
40245
|
+
messageId: this.messageId,
|
|
40246
|
+
stickyTarget: this.stickyTargets,
|
|
40247
|
+
agents
|
|
40248
|
+
};
|
|
40249
|
+
await writeFile5(this.manifestPath(), JSON.stringify(manifest, null, 2), "utf8");
|
|
40250
|
+
} catch (err) {
|
|
40251
|
+
console.error("[manifest] write failed:", err);
|
|
40252
|
+
}
|
|
39818
40253
|
});
|
|
40254
|
+
return this.manifestSavePromise;
|
|
40255
|
+
}
|
|
40256
|
+
async loadManifest() {
|
|
39819
40257
|
try {
|
|
39820
|
-
|
|
39821
|
-
|
|
39822
|
-
if (
|
|
39823
|
-
|
|
40258
|
+
const content = await readFile5(this.manifestPath(), "utf8");
|
|
40259
|
+
const manifest = JSON.parse(content);
|
|
40260
|
+
if (Array.isArray(manifest.stickyTarget)) {
|
|
40261
|
+
this.stickyTargets = manifest.stickyTarget;
|
|
40262
|
+
}
|
|
40263
|
+
const agentMap = manifest.agents ?? {};
|
|
40264
|
+
for (const [name, data] of Object.entries(agentMap)) {
|
|
40265
|
+
const adapter = this.agents.get(name);
|
|
40266
|
+
const agentData = data;
|
|
40267
|
+
if (!adapter || !agentData)
|
|
40268
|
+
continue;
|
|
40269
|
+
if (typeof agentData.sdkSessionId === "string" && agentData.sdkSessionId) {
|
|
40270
|
+
adapter.setSdkSessionId(agentData.sdkSessionId);
|
|
40271
|
+
}
|
|
40272
|
+
if (typeof agentData.lastSeenId === "number") {
|
|
40273
|
+
this.lastSeenByAgent.set(name, agentData.lastSeenId);
|
|
40274
|
+
}
|
|
39824
40275
|
}
|
|
40276
|
+
} catch (err) {
|
|
40277
|
+
console.error("[manifest] load failed (agents start fresh):", err);
|
|
39825
40278
|
}
|
|
39826
40279
|
}
|
|
40280
|
+
cancelAgents(names) {
|
|
40281
|
+
for (const name of names) {
|
|
40282
|
+
this.queueManager.abortAgent(name);
|
|
40283
|
+
this.onActivity(name, "idle");
|
|
40284
|
+
}
|
|
40285
|
+
}
|
|
40286
|
+
async abortAll() {
|
|
40287
|
+
this.queueManager.abortAll();
|
|
40288
|
+
await this.saveManifest();
|
|
40289
|
+
}
|
|
39827
40290
|
timeoutFor(agentName) {
|
|
39828
40291
|
return this.agentTimeouts.get(agentName) ?? this.defaultTimeout;
|
|
39829
40292
|
}
|
|
@@ -39857,6 +40320,21 @@ function createSessionId() {
|
|
|
39857
40320
|
const rand = randomBytes(4).toString("hex");
|
|
39858
40321
|
return `${timestamp}-${process.pid}-${rand}`;
|
|
39859
40322
|
}
|
|
40323
|
+
function extractNextSelectors(messages) {
|
|
40324
|
+
const selectors = [];
|
|
40325
|
+
for (const msg of messages) {
|
|
40326
|
+
const regex = /@next\s*:\s*([A-Za-z0-9_-]+)/gi;
|
|
40327
|
+
let match = null;
|
|
40328
|
+
while ((match = regex.exec(msg.text)) !== null) {
|
|
40329
|
+
selectors.push(match[1]);
|
|
40330
|
+
}
|
|
40331
|
+
const controlMatch = msg.text.match(/@control[\s\S]*?next\s*:\s*([A-Za-z0-9_-]+)[\s\S]*?@end/i);
|
|
40332
|
+
if (controlMatch?.[1]) {
|
|
40333
|
+
selectors.push(controlMatch[1]);
|
|
40334
|
+
}
|
|
40335
|
+
}
|
|
40336
|
+
return selectors;
|
|
40337
|
+
}
|
|
39860
40338
|
|
|
39861
40339
|
// src/ui/App.tsx
|
|
39862
40340
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -39868,14 +40346,56 @@ function nextSystemId() {
|
|
|
39868
40346
|
systemIdCounter -= 1;
|
|
39869
40347
|
return systemIdCounter;
|
|
39870
40348
|
}
|
|
39871
|
-
function useOrchestrator(orchestrator
|
|
40349
|
+
function useOrchestrator(orchestrator) {
|
|
39872
40350
|
const [messages, setMessages] = createSignal([]);
|
|
39873
40351
|
const [agentStates, setAgentStates] = createSignal(new Map(orchestrator.listAgents().map((a) => [a.name, "idle"])));
|
|
39874
|
-
const [stickyTarget,
|
|
40352
|
+
const [stickyTarget, setStickyTargetSignal] = createSignal(orchestrator.getStickyTarget());
|
|
40353
|
+
const setStickyTarget = (targets) => {
|
|
40354
|
+
setStickyTargetSignal(targets);
|
|
40355
|
+
orchestrator.setStickyTarget(targets);
|
|
40356
|
+
};
|
|
39875
40357
|
const [dispatching, setDispatching] = createSignal(false);
|
|
40358
|
+
const [queueCounts, setQueueCounts] = createSignal(new Map(orchestrator.listAgents().map((a) => [a.name, 0])));
|
|
39876
40359
|
let projectFolderReady = false;
|
|
39877
|
-
|
|
39878
|
-
|
|
40360
|
+
const agentProviders = new Map(orchestrator.listAgents().map((a) => [a.name.toUpperCase(), a.provider]));
|
|
40361
|
+
const agentTagsMap = new Map(orchestrator.listAgents().map((a) => [a.name.toUpperCase(), a.tag]));
|
|
40362
|
+
const nameMap = new Map(orchestrator.listAgents().map((a) => [a.name.toUpperCase(), a.name]));
|
|
40363
|
+
const updateQueueCounts = () => {
|
|
40364
|
+
const status = orchestrator.getQueueStatus();
|
|
40365
|
+
setQueueCounts(new Map(status.map((s) => [s.name, s.pending])));
|
|
40366
|
+
};
|
|
40367
|
+
orchestrator.setCallbacks((msg) => {
|
|
40368
|
+
const provider = agentProviders.get(msg.from) ?? "";
|
|
40369
|
+
const tag = agentTagsMap.get(msg.from) ?? "";
|
|
40370
|
+
const display = {
|
|
40371
|
+
...msg,
|
|
40372
|
+
type: "agent",
|
|
40373
|
+
provider,
|
|
40374
|
+
tag
|
|
40375
|
+
};
|
|
40376
|
+
setMessages((prev) => [...prev, display]);
|
|
40377
|
+
const originalName = nameMap.get(msg.from) ?? msg.from;
|
|
40378
|
+
setAgentStates((prev) => {
|
|
40379
|
+
const next = new Map(prev);
|
|
40380
|
+
const isErr = msg.text.startsWith("[Adapter Error]") || msg.text.startsWith("[Error]") || msg.text.startsWith("[Timeout]");
|
|
40381
|
+
next.set(originalName, isErr ? "error" : "idle");
|
|
40382
|
+
return next;
|
|
40383
|
+
});
|
|
40384
|
+
setDispatching(orchestrator.dispatching);
|
|
40385
|
+
updateQueueCounts();
|
|
40386
|
+
}, (agentName, activity) => {
|
|
40387
|
+
const originalName = nameMap.get(agentName.toUpperCase()) ?? agentName;
|
|
40388
|
+
setAgentStates((prev) => {
|
|
40389
|
+
const next = new Map(prev);
|
|
40390
|
+
next.set(originalName, activity);
|
|
40391
|
+
return next;
|
|
40392
|
+
});
|
|
40393
|
+
setDispatching(orchestrator.dispatching);
|
|
40394
|
+
updateQueueCounts();
|
|
40395
|
+
}, (text) => {
|
|
40396
|
+
addSystemMessage(text);
|
|
40397
|
+
updateQueueCounts();
|
|
40398
|
+
});
|
|
39879
40399
|
const dispatch = async (line) => {
|
|
39880
40400
|
if (!line.trim())
|
|
39881
40401
|
return;
|
|
@@ -39889,7 +40409,7 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
39889
40409
|
if (explicitTargets && explicitTargets.length > 0) {
|
|
39890
40410
|
setStickyTarget(explicitTargets);
|
|
39891
40411
|
}
|
|
39892
|
-
const targets = explicitTargets ?? stickyTarget();
|
|
40412
|
+
const targets = explicitTargets ?? stickyTarget() ?? Array.from(orchestrator.listAgents().map((a) => a.name));
|
|
39893
40413
|
if (!projectFolderReady) {
|
|
39894
40414
|
await initProjectFolder(process.cwd());
|
|
39895
40415
|
projectFolderReady = true;
|
|
@@ -39902,11 +40422,7 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
39902
40422
|
};
|
|
39903
40423
|
setMessages((prev) => [...prev, userDisplay]);
|
|
39904
40424
|
setDispatching(true);
|
|
39905
|
-
|
|
39906
|
-
await dispatchWithHandoffs(orchestrator, targets, maxAutoHops, agentProviders, agentTags, setMessages, setAgentStates);
|
|
39907
|
-
} finally {
|
|
39908
|
-
setDispatching(false);
|
|
39909
|
-
}
|
|
40425
|
+
orchestrator.dispatchToTargets(targets);
|
|
39910
40426
|
};
|
|
39911
40427
|
const addSystemMessage = (text) => {
|
|
39912
40428
|
const msg = {
|
|
@@ -39918,89 +40434,17 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
39918
40434
|
};
|
|
39919
40435
|
setMessages((prev) => [...prev, msg]);
|
|
39920
40436
|
};
|
|
40437
|
+
const addDisplayMessage = (msg) => {
|
|
40438
|
+
setMessages((prev) => [...prev, msg]);
|
|
40439
|
+
};
|
|
39921
40440
|
const clearMessages = () => {
|
|
39922
40441
|
orchestrator.clearConversation();
|
|
39923
40442
|
setMessages([]);
|
|
39924
40443
|
};
|
|
39925
|
-
|
|
39926
|
-
|
|
39927
|
-
|
|
39928
|
-
|
|
39929
|
-
let hops = 0;
|
|
39930
|
-
while (true) {
|
|
39931
|
-
const targetNames = targets ?? Array.from(orchestrator.listAgents().map((a) => a.name));
|
|
39932
|
-
setAgentStates((prev) => {
|
|
39933
|
-
const next = new Map(prev);
|
|
39934
|
-
for (const name of targetNames) {
|
|
39935
|
-
next.set(name, "thinking");
|
|
39936
|
-
}
|
|
39937
|
-
return next;
|
|
39938
|
-
});
|
|
39939
|
-
const nameMap = new Map(orchestrator.listAgents().map((a) => [a.name.toUpperCase(), a.name]));
|
|
39940
|
-
const batch = [];
|
|
39941
|
-
await orchestrator.fanOutWithProgress(targets, (msg) => {
|
|
39942
|
-
batch.push(msg);
|
|
39943
|
-
const provider = agentProviders.get(msg.from) ?? "";
|
|
39944
|
-
const tag = agentTags.get(msg.from) ?? "";
|
|
39945
|
-
const display = {
|
|
39946
|
-
...msg,
|
|
39947
|
-
type: "agent",
|
|
39948
|
-
provider,
|
|
39949
|
-
tag
|
|
39950
|
-
};
|
|
39951
|
-
setMessages((prev) => [...prev, display]);
|
|
39952
|
-
const originalName = nameMap.get(msg.from) ?? msg.from;
|
|
39953
|
-
setAgentStates((prev) => {
|
|
39954
|
-
const next = new Map(prev);
|
|
39955
|
-
next.set(originalName, msg.text.startsWith("[Adapter Error]") ? "error" : "idle");
|
|
39956
|
-
return next;
|
|
39957
|
-
});
|
|
39958
|
-
});
|
|
39959
|
-
setAgentStates((prev) => {
|
|
39960
|
-
const next = new Map(prev);
|
|
39961
|
-
for (const name of targetNames) {
|
|
39962
|
-
if (next.get(name) === "thinking") {
|
|
39963
|
-
next.set(name, "idle");
|
|
39964
|
-
}
|
|
39965
|
-
}
|
|
39966
|
-
return next;
|
|
39967
|
-
});
|
|
39968
|
-
const nextSelectors = extractNextSelectors(batch);
|
|
39969
|
-
if (nextSelectors.length === 0)
|
|
39970
|
-
return;
|
|
39971
|
-
const humanTag = orchestrator.getHumanTag().toLowerCase();
|
|
39972
|
-
const humanName = orchestrator.getHumanName().toLowerCase();
|
|
39973
|
-
const agentSelectors = nextSelectors.filter((s) => {
|
|
39974
|
-
const n = s.toLowerCase();
|
|
39975
|
-
return n !== humanTag && n !== humanName;
|
|
39976
|
-
});
|
|
39977
|
-
if (agentSelectors.length === 0)
|
|
39978
|
-
return;
|
|
39979
|
-
const resolvedTargets = Array.from(new Set(agentSelectors.flatMap((s) => orchestrator.resolveTargets(s))));
|
|
39980
|
-
if (resolvedTargets.length === 0)
|
|
39981
|
-
return;
|
|
39982
|
-
hops += 1;
|
|
39983
|
-
if (Number.isFinite(maxHops) && hops >= maxHops) {
|
|
39984
|
-
const systemMsg = {
|
|
39985
|
-
id: nextSystemId(),
|
|
39986
|
-
from: "SYSTEM",
|
|
39987
|
-
text: `Stopped auto-handoff after ${maxHops} hops.`,
|
|
39988
|
-
createdAt: new Date().toISOString(),
|
|
39989
|
-
type: "system"
|
|
39990
|
-
};
|
|
39991
|
-
setMessages((prev) => [...prev, systemMsg]);
|
|
39992
|
-
return;
|
|
39993
|
-
}
|
|
39994
|
-
const handoffMsg = {
|
|
39995
|
-
id: nextSystemId(),
|
|
39996
|
-
from: "SYSTEM",
|
|
39997
|
-
text: `Auto handoff via @next to ${resolvedTargets.join(", ")}`,
|
|
39998
|
-
createdAt: new Date().toISOString(),
|
|
39999
|
-
type: "system"
|
|
40000
|
-
};
|
|
40001
|
-
setMessages((prev) => [...prev, handoffMsg]);
|
|
40002
|
-
targets = resolvedTargets;
|
|
40003
|
-
}
|
|
40444
|
+
const refreshStickyTarget = () => {
|
|
40445
|
+
setStickyTargetSignal(orchestrator.getStickyTarget());
|
|
40446
|
+
};
|
|
40447
|
+
return { messages, agentStates, queueCounts, stickyTarget, dispatching, dispatch, addSystemMessage, addDisplayMessage, clearMessages, refreshStickyTarget };
|
|
40004
40448
|
}
|
|
40005
40449
|
function getChangedFiles() {
|
|
40006
40450
|
return new Promise((resolve4) => {
|
|
@@ -40015,21 +40459,6 @@ function getChangedFiles() {
|
|
|
40015
40459
|
});
|
|
40016
40460
|
});
|
|
40017
40461
|
}
|
|
40018
|
-
function extractNextSelectors(messages) {
|
|
40019
|
-
const selectors = [];
|
|
40020
|
-
for (const msg of messages) {
|
|
40021
|
-
const regex = /@next\s*:\s*([A-Za-z0-9_-]+)/gi;
|
|
40022
|
-
let match = null;
|
|
40023
|
-
while ((match = regex.exec(msg.text)) !== null) {
|
|
40024
|
-
selectors.push(match[1]);
|
|
40025
|
-
}
|
|
40026
|
-
const controlMatch = msg.text.match(/@control[\s\S]*?next\s*:\s*([A-Za-z0-9_-]+)[\s\S]*?@end/i);
|
|
40027
|
-
if (controlMatch?.[1]) {
|
|
40028
|
-
selectors.push(controlMatch[1]);
|
|
40029
|
-
}
|
|
40030
|
-
}
|
|
40031
|
-
return selectors;
|
|
40032
|
-
}
|
|
40033
40462
|
function parseRouting(line) {
|
|
40034
40463
|
const mentionRegex = /(^|[^A-Za-z0-9_-])@([A-Za-z0-9_-]+)\b/g;
|
|
40035
40464
|
const mentions = [];
|
|
@@ -40118,27 +40547,21 @@ function MessageBubble(props) {
|
|
|
40118
40547
|
}
|
|
40119
40548
|
|
|
40120
40549
|
// src/ui/constants.ts
|
|
40121
|
-
var SPINNER_FRAMES =
|
|
40550
|
+
var SPINNER_FRAMES = "\u280B\u2819\u281A\u281E\u2816\u2826\u2834\u2832\u2833\u2813".split("");
|
|
40551
|
+
var ACTIVITY_SPINNERS = {
|
|
40552
|
+
thinking_bkp: "\u2733\u2734\u2736\u2735\u2737\u2738\u2739\u273A".split(""),
|
|
40553
|
+
thinking: " ..ooOO@@@@@@*".split(""),
|
|
40554
|
+
writing: "\u258F\u258E\u258D\u258C\u258B\u258A\u2589\u2588\u2589\u258A\u258B\u258C\u258D\u258E".split(""),
|
|
40555
|
+
reading: ["\u2801", "\u2809", "\u280B", "\u281B", "\u281F", "\u283F", "\u287F", "\u28FF"],
|
|
40556
|
+
running: [" ", "\u2591", "\u2592", "\u2593", "\u2588"],
|
|
40557
|
+
searching: "\u25D0\u25D3\u25D1\u25D2".split("")
|
|
40558
|
+
};
|
|
40559
|
+
var SUPERSCRIPT_DIGITS = ["\u2070", "\xB9", "\xB2", "\xB3", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079"];
|
|
40122
40560
|
|
|
40123
40561
|
// src/ui/StatusBar.tsx
|
|
40124
40562
|
var PULSE_COLORS = ["#005F87", "#0087AF", "#00AFD7", "#00D7FF", "#5FF", "#00D7FF", "#0087AF"];
|
|
40125
|
-
|
|
40126
|
-
|
|
40127
|
-
createEffect(() => {
|
|
40128
|
-
if (!active()) {
|
|
40129
|
-
setFrame(0);
|
|
40130
|
-
return;
|
|
40131
|
-
}
|
|
40132
|
-
const interval = setInterval(() => {
|
|
40133
|
-
setFrame((f) => (f + 1) % (SPINNER_FRAMES.length * PULSE_COLORS.length));
|
|
40134
|
-
}, 80);
|
|
40135
|
-
onCleanup(() => clearInterval(interval));
|
|
40136
|
-
});
|
|
40137
|
-
return {
|
|
40138
|
-
spinner: () => active() ? SPINNER_FRAMES[frame() % SPINNER_FRAMES.length] : "",
|
|
40139
|
-
color: () => active() ? PULSE_COLORS[frame() % PULSE_COLORS.length] : COLORS.textMuted
|
|
40140
|
-
};
|
|
40141
|
-
}
|
|
40563
|
+
var [globalTick, setGlobalTick] = createSignal(0);
|
|
40564
|
+
setInterval(() => setGlobalTick((t2) => t2 + 1), 80);
|
|
40142
40565
|
function StatusBar(props) {
|
|
40143
40566
|
const targetNames = () => props.stickyTarget ?? props.agents.map((a) => a.name);
|
|
40144
40567
|
const isTargeted = (name) => targetNames().includes(name);
|
|
@@ -40186,65 +40609,59 @@ function StatusBar(props) {
|
|
|
40186
40609
|
}), _el$4);
|
|
40187
40610
|
insertNode(_el$4, createTextNode(`| /info`));
|
|
40188
40611
|
setProp(_el$6, "flexDirection", "row");
|
|
40189
|
-
setProp(_el$6, "gap", 2);
|
|
40190
40612
|
insert(_el$6, createComponent2(For, {
|
|
40191
40613
|
get each() {
|
|
40192
40614
|
return props.agents;
|
|
40193
40615
|
},
|
|
40194
|
-
children: (a) => createComponent2(AgentChip, {
|
|
40616
|
+
children: (a, i) => [createComponent2(AgentChip, {
|
|
40195
40617
|
get name() {
|
|
40196
40618
|
return a.name;
|
|
40197
40619
|
},
|
|
40198
|
-
|
|
40199
|
-
|
|
40200
|
-
|
|
40201
|
-
|
|
40620
|
+
getState: () => props.agentStates.get(a.name) ?? "idle",
|
|
40621
|
+
getQueued: () => props.queueCounts?.get(a.name) ?? 0
|
|
40622
|
+
}), memo2(() => memo2(() => i() < props.agents.length - 1)() ? (() => {
|
|
40623
|
+
var _el$12 = createElement("text");
|
|
40624
|
+
insertNode(_el$12, createTextNode(` \u2502 `));
|
|
40625
|
+
effect((_$p) => setProp(_el$12, "fg", COLORS.textDim, _$p));
|
|
40626
|
+
return _el$12;
|
|
40627
|
+
})() : null)]
|
|
40202
40628
|
}));
|
|
40203
40629
|
effect((_$p) => setProp(_el$4, "fg", COLORS.textDim, _$p));
|
|
40204
40630
|
return _el$;
|
|
40205
40631
|
})();
|
|
40206
40632
|
}
|
|
40633
|
+
function toSuperscript(n) {
|
|
40634
|
+
if (n <= 0)
|
|
40635
|
+
return "";
|
|
40636
|
+
return String(n).split("").map((d2) => SUPERSCRIPT_DIGITS[parseInt(d2, 10)] ?? d2).join("");
|
|
40637
|
+
}
|
|
40207
40638
|
function AgentChip(props) {
|
|
40208
|
-
const {
|
|
40209
|
-
|
|
40210
|
-
|
|
40211
|
-
}
|
|
40212
|
-
|
|
40213
|
-
|
|
40214
|
-
|
|
40215
|
-
|
|
40216
|
-
|
|
40217
|
-
|
|
40218
|
-
|
|
40219
|
-
|
|
40220
|
-
|
|
40221
|
-
|
|
40222
|
-
|
|
40223
|
-
|
|
40224
|
-
|
|
40225
|
-
|
|
40226
|
-
|
|
40227
|
-
|
|
40228
|
-
|
|
40229
|
-
|
|
40230
|
-
|
|
40231
|
-
|
|
40232
|
-
|
|
40233
|
-
|
|
40234
|
-
get when() {
|
|
40235
|
-
return props.state === "thinking";
|
|
40236
|
-
},
|
|
40237
|
-
get children() {
|
|
40238
|
-
var _el$14 = createElement("text"), _el$15 = createTextNode(` `);
|
|
40239
|
-
insertNode(_el$14, _el$15);
|
|
40240
|
-
insert(_el$14, () => props.name, _el$15);
|
|
40241
|
-
insert(_el$14, spinner, null);
|
|
40242
|
-
effect((_$p) => setProp(_el$14, "fg", color(), _$p));
|
|
40243
|
-
return _el$14;
|
|
40244
|
-
}
|
|
40245
|
-
})];
|
|
40246
|
-
}
|
|
40247
|
-
});
|
|
40639
|
+
const isActive = () => {
|
|
40640
|
+
const s = props.getState();
|
|
40641
|
+
return s !== "idle" && s !== "error" && s !== "queued";
|
|
40642
|
+
};
|
|
40643
|
+
const frames = () => ACTIVITY_SPINNERS[props.getState()] ?? SPINNER_FRAMES;
|
|
40644
|
+
const tick = () => globalTick();
|
|
40645
|
+
const spinner = () => isActive() ? frames()[tick() % frames().length] : " ";
|
|
40646
|
+
const pulseColor = () => isActive() ? PULSE_COLORS[tick() % PULSE_COLORS.length] : COLORS.textMuted;
|
|
40647
|
+
const queueSlot = () => props.getQueued() > 0 ? toSuperscript(props.getQueued()) : " ";
|
|
40648
|
+
const stateColor = () => {
|
|
40649
|
+
if (props.getState() === "error")
|
|
40650
|
+
return COLORS.error;
|
|
40651
|
+
if (isActive())
|
|
40652
|
+
return pulseColor();
|
|
40653
|
+
return COLORS.textMuted;
|
|
40654
|
+
};
|
|
40655
|
+
return (() => {
|
|
40656
|
+
var _el$14 = createElement("text"), _el$15 = createTextNode(` `);
|
|
40657
|
+
insertNode(_el$14, _el$15);
|
|
40658
|
+
insert(_el$14, queueSlot, _el$15);
|
|
40659
|
+
insert(_el$14, () => props.name, _el$15);
|
|
40660
|
+
insert(_el$14, spinner, null);
|
|
40661
|
+
insert(_el$14, () => props.getState() === "error" ? " ERR" : "", null);
|
|
40662
|
+
effect((_$p) => setProp(_el$14, "fg", stateColor(), _$p));
|
|
40663
|
+
return _el$14;
|
|
40664
|
+
})();
|
|
40248
40665
|
}
|
|
40249
40666
|
|
|
40250
40667
|
// src/ui/InputLine.tsx
|
|
@@ -40500,7 +40917,7 @@ import { userInfo as userInfo2 } from "os";
|
|
|
40500
40917
|
|
|
40501
40918
|
// src/config/detector.ts
|
|
40502
40919
|
import { spawn as spawn3 } from "child_process";
|
|
40503
|
-
var DETECT_TIMEOUT =
|
|
40920
|
+
var DETECT_TIMEOUT = 1e4;
|
|
40504
40921
|
function detectBinary(command) {
|
|
40505
40922
|
return new Promise((resolve4) => {
|
|
40506
40923
|
const timer = setTimeout(() => resolve4({ available: false }), DETECT_TIMEOUT);
|
|
@@ -42299,6 +42716,178 @@ function InfoPanel(props) {
|
|
|
42299
42716
|
})();
|
|
42300
42717
|
}
|
|
42301
42718
|
|
|
42719
|
+
// src/ui/CancelPanel.tsx
|
|
42720
|
+
function CancelPanel(props) {
|
|
42721
|
+
const items = () => props.activeAgents;
|
|
42722
|
+
const [cursor, setCursor] = createSignal(0);
|
|
42723
|
+
const [selected, setSelected] = createSignal(new Set);
|
|
42724
|
+
createEffect(() => {
|
|
42725
|
+
if (props.activeAgents.length === 0) {
|
|
42726
|
+
props.onClose();
|
|
42727
|
+
}
|
|
42728
|
+
});
|
|
42729
|
+
useKeyboard((key) => {
|
|
42730
|
+
if (key.name === "escape") {
|
|
42731
|
+
props.onClose();
|
|
42732
|
+
return;
|
|
42733
|
+
}
|
|
42734
|
+
if (key.name === "return") {
|
|
42735
|
+
const sel = selected();
|
|
42736
|
+
if (sel.size === 0) {
|
|
42737
|
+
props.onClose();
|
|
42738
|
+
return;
|
|
42739
|
+
}
|
|
42740
|
+
const names = [...sel];
|
|
42741
|
+
props.onCancel(names);
|
|
42742
|
+
return;
|
|
42743
|
+
}
|
|
42744
|
+
if (key.name === "up") {
|
|
42745
|
+
setCursor((c) => Math.max(0, c - 1));
|
|
42746
|
+
return;
|
|
42747
|
+
}
|
|
42748
|
+
if (key.name === "down") {
|
|
42749
|
+
setCursor((c) => Math.min(items().length - 1, c + 1));
|
|
42750
|
+
return;
|
|
42751
|
+
}
|
|
42752
|
+
if (key.name === "space" || key.sequence === " ") {
|
|
42753
|
+
const item = items()[cursor()];
|
|
42754
|
+
if (!item)
|
|
42755
|
+
return;
|
|
42756
|
+
setSelected((prev) => {
|
|
42757
|
+
const next = new Set(prev);
|
|
42758
|
+
if (next.has(item)) {
|
|
42759
|
+
next.delete(item);
|
|
42760
|
+
} else {
|
|
42761
|
+
next.add(item);
|
|
42762
|
+
}
|
|
42763
|
+
return next;
|
|
42764
|
+
});
|
|
42765
|
+
return;
|
|
42766
|
+
}
|
|
42767
|
+
});
|
|
42768
|
+
const totalW = 40;
|
|
42769
|
+
return (() => {
|
|
42770
|
+
var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("box"), _el$4 = createElement("text"), _el$5 = createElement("strong"), _el$7 = createElement("text"), _el$9 = createElement("text"), _el$1 = createElement("text"), _el$10 = createElement("span"), _el$12 = createElement("span"), _el$14 = createElement("span"), _el$16 = createElement("span"), _el$18 = createElement("span"), _el$20 = createElement("span");
|
|
42771
|
+
insertNode(_el$, _el$2);
|
|
42772
|
+
setProp(_el$, "position", "absolute");
|
|
42773
|
+
setProp(_el$, "width", "100%");
|
|
42774
|
+
setProp(_el$, "height", "100%");
|
|
42775
|
+
setProp(_el$, "justifyContent", "center");
|
|
42776
|
+
setProp(_el$, "alignItems", "center");
|
|
42777
|
+
setProp(_el$, "zIndex", 10);
|
|
42778
|
+
insertNode(_el$2, _el$3);
|
|
42779
|
+
setProp(_el$2, "border", true);
|
|
42780
|
+
setProp(_el$2, "borderStyle", "rounded");
|
|
42781
|
+
setProp(_el$2, "paddingX", 3);
|
|
42782
|
+
setProp(_el$2, "paddingY", 1);
|
|
42783
|
+
insertNode(_el$3, _el$4);
|
|
42784
|
+
insertNode(_el$3, _el$7);
|
|
42785
|
+
insertNode(_el$3, _el$9);
|
|
42786
|
+
insertNode(_el$3, _el$1);
|
|
42787
|
+
setProp(_el$3, "flexDirection", "column");
|
|
42788
|
+
insertNode(_el$4, _el$5);
|
|
42789
|
+
setProp(_el$4, "alignSelf", "center");
|
|
42790
|
+
insertNode(_el$5, createTextNode(`Cancel Agents`));
|
|
42791
|
+
insertNode(_el$7, createTextNode(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
42792
|
+
setProp(_el$7, "marginTop", 1);
|
|
42793
|
+
insert(_el$3, createComponent2(For, {
|
|
42794
|
+
get each() {
|
|
42795
|
+
return items();
|
|
42796
|
+
},
|
|
42797
|
+
children: (item, i) => {
|
|
42798
|
+
const isSelected = () => selected().has(item);
|
|
42799
|
+
const isCursor = () => cursor() === i();
|
|
42800
|
+
const bullet = () => isSelected() ? "\u25A0" : "\u25A1";
|
|
42801
|
+
const bulletColor = () => isSelected() ? COLORS.error : COLORS.textDim;
|
|
42802
|
+
const labelColor = () => isCursor() ? COLORS.textPrimary : COLORS.textMuted;
|
|
42803
|
+
const bgColor = () => isCursor() ? COLORS.bgFocus : undefined;
|
|
42804
|
+
return (() => {
|
|
42805
|
+
var _el$22 = createElement("text"), _el$23 = createElement("span"), _el$24 = createTextNode(` `), _el$25 = createTextNode(` `), _el$26 = createElement("span");
|
|
42806
|
+
insertNode(_el$22, _el$23);
|
|
42807
|
+
insertNode(_el$22, _el$26);
|
|
42808
|
+
setProp(_el$22, "selectable", false);
|
|
42809
|
+
insertNode(_el$23, _el$24);
|
|
42810
|
+
insertNode(_el$23, _el$25);
|
|
42811
|
+
insert(_el$23, bullet, _el$25);
|
|
42812
|
+
insert(_el$26, item);
|
|
42813
|
+
effect((_p$) => {
|
|
42814
|
+
var _v$10 = bgColor(), _v$11 = {
|
|
42815
|
+
fg: bulletColor()
|
|
42816
|
+
}, _v$12 = {
|
|
42817
|
+
fg: labelColor()
|
|
42818
|
+
};
|
|
42819
|
+
_v$10 !== _p$.e && (_p$.e = setProp(_el$22, "bg", _v$10, _p$.e));
|
|
42820
|
+
_v$11 !== _p$.t && (_p$.t = setProp(_el$23, "style", _v$11, _p$.t));
|
|
42821
|
+
_v$12 !== _p$.a && (_p$.a = setProp(_el$26, "style", _v$12, _p$.a));
|
|
42822
|
+
return _p$;
|
|
42823
|
+
}, {
|
|
42824
|
+
e: undefined,
|
|
42825
|
+
t: undefined,
|
|
42826
|
+
a: undefined
|
|
42827
|
+
});
|
|
42828
|
+
return _el$22;
|
|
42829
|
+
})();
|
|
42830
|
+
}
|
|
42831
|
+
}), _el$9);
|
|
42832
|
+
insertNode(_el$9, createTextNode(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`));
|
|
42833
|
+
setProp(_el$9, "marginTop", 1);
|
|
42834
|
+
insertNode(_el$1, _el$10);
|
|
42835
|
+
insertNode(_el$1, _el$12);
|
|
42836
|
+
insertNode(_el$1, _el$14);
|
|
42837
|
+
insertNode(_el$1, _el$16);
|
|
42838
|
+
insertNode(_el$1, _el$18);
|
|
42839
|
+
insertNode(_el$1, _el$20);
|
|
42840
|
+
setProp(_el$1, "marginTop", 1);
|
|
42841
|
+
setProp(_el$1, "alignSelf", "center");
|
|
42842
|
+
insertNode(_el$10, createTextNode(`Space`));
|
|
42843
|
+
insertNode(_el$12, createTextNode(` toggle `));
|
|
42844
|
+
insertNode(_el$14, createTextNode(`Enter`));
|
|
42845
|
+
insertNode(_el$16, createTextNode(` kill `));
|
|
42846
|
+
insertNode(_el$18, createTextNode(`Esc`));
|
|
42847
|
+
insertNode(_el$20, createTextNode(` back`));
|
|
42848
|
+
effect((_p$) => {
|
|
42849
|
+
var _v$ = COLORS.error, _v$2 = COLORS.bgPanel, _v$3 = COLORS.error, _v$4 = COLORS.borderStrong, _v$5 = COLORS.borderStrong, _v$6 = {
|
|
42850
|
+
fg: COLORS.textFaint
|
|
42851
|
+
}, _v$7 = {
|
|
42852
|
+
fg: COLORS.textDim
|
|
42853
|
+
}, _v$8 = {
|
|
42854
|
+
fg: COLORS.error
|
|
42855
|
+
}, _v$9 = {
|
|
42856
|
+
fg: COLORS.textDim
|
|
42857
|
+
}, _v$0 = {
|
|
42858
|
+
fg: COLORS.textFaint
|
|
42859
|
+
}, _v$1 = {
|
|
42860
|
+
fg: COLORS.textDim
|
|
42861
|
+
};
|
|
42862
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$2, "borderColor", _v$, _p$.e));
|
|
42863
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$2, "backgroundColor", _v$2, _p$.t));
|
|
42864
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "fg", _v$3, _p$.a));
|
|
42865
|
+
_v$4 !== _p$.o && (_p$.o = setProp(_el$7, "fg", _v$4, _p$.o));
|
|
42866
|
+
_v$5 !== _p$.i && (_p$.i = setProp(_el$9, "fg", _v$5, _p$.i));
|
|
42867
|
+
_v$6 !== _p$.n && (_p$.n = setProp(_el$10, "style", _v$6, _p$.n));
|
|
42868
|
+
_v$7 !== _p$.s && (_p$.s = setProp(_el$12, "style", _v$7, _p$.s));
|
|
42869
|
+
_v$8 !== _p$.h && (_p$.h = setProp(_el$14, "style", _v$8, _p$.h));
|
|
42870
|
+
_v$9 !== _p$.r && (_p$.r = setProp(_el$16, "style", _v$9, _p$.r));
|
|
42871
|
+
_v$0 !== _p$.d && (_p$.d = setProp(_el$18, "style", _v$0, _p$.d));
|
|
42872
|
+
_v$1 !== _p$.l && (_p$.l = setProp(_el$20, "style", _v$1, _p$.l));
|
|
42873
|
+
return _p$;
|
|
42874
|
+
}, {
|
|
42875
|
+
e: undefined,
|
|
42876
|
+
t: undefined,
|
|
42877
|
+
a: undefined,
|
|
42878
|
+
o: undefined,
|
|
42879
|
+
i: undefined,
|
|
42880
|
+
n: undefined,
|
|
42881
|
+
s: undefined,
|
|
42882
|
+
h: undefined,
|
|
42883
|
+
r: undefined,
|
|
42884
|
+
d: undefined,
|
|
42885
|
+
l: undefined
|
|
42886
|
+
});
|
|
42887
|
+
return _el$;
|
|
42888
|
+
})();
|
|
42889
|
+
}
|
|
42890
|
+
|
|
42302
42891
|
// src/ui/App.tsx
|
|
42303
42892
|
function copyToClipboard(text) {
|
|
42304
42893
|
const proc = spawn4("pbcopy", [], {
|
|
@@ -42323,12 +42912,15 @@ function App(props) {
|
|
|
42323
42912
|
const {
|
|
42324
42913
|
messages,
|
|
42325
42914
|
agentStates,
|
|
42915
|
+
queueCounts,
|
|
42326
42916
|
stickyTarget,
|
|
42327
42917
|
dispatching,
|
|
42328
42918
|
dispatch,
|
|
42329
42919
|
addSystemMessage,
|
|
42330
|
-
|
|
42331
|
-
|
|
42920
|
+
addDisplayMessage,
|
|
42921
|
+
clearMessages,
|
|
42922
|
+
refreshStickyTarget
|
|
42923
|
+
} = useOrchestrator(props.orchestrator);
|
|
42332
42924
|
const humanName = props.orchestrator.getHumanName();
|
|
42333
42925
|
const agents = props.orchestrator.listAgents();
|
|
42334
42926
|
let scrollRef = null;
|
|
@@ -42336,25 +42928,67 @@ function App(props) {
|
|
|
42336
42928
|
const [freshConfig, setFreshConfig] = createSignal(props.config);
|
|
42337
42929
|
const [showAgents, setShowAgents] = createSignal(false);
|
|
42338
42930
|
const [showInfo, setShowInfo] = createSignal(false);
|
|
42339
|
-
|
|
42340
|
-
|
|
42341
|
-
|
|
42931
|
+
const [showCancel, setShowCancel] = createSignal(false);
|
|
42932
|
+
const resumeSession = async (sessionId) => {
|
|
42933
|
+
try {
|
|
42934
|
+
const restored = await props.orchestrator.loadTranscript(sessionId);
|
|
42935
|
+
const displayMsgs = restored.map((msg) => {
|
|
42936
|
+
const isHuman = msg.from.toUpperCase() === humanName.toUpperCase();
|
|
42937
|
+
const agentInfo = agents.find((a) => a.name.toUpperCase() === msg.from.toUpperCase());
|
|
42938
|
+
return {
|
|
42939
|
+
...msg,
|
|
42940
|
+
type: isHuman ? "user" : "agent",
|
|
42941
|
+
provider: agentInfo?.provider ?? "",
|
|
42942
|
+
tag: agentInfo?.tag ?? ""
|
|
42943
|
+
};
|
|
42944
|
+
});
|
|
42945
|
+
for (const msg of displayMsgs) {
|
|
42946
|
+
addDisplayMessage(msg);
|
|
42947
|
+
}
|
|
42948
|
+
refreshStickyTarget();
|
|
42949
|
+
addSystemMessage(`Resumed session ${sessionId} (${restored.length} messages)`);
|
|
42950
|
+
} catch (err) {
|
|
42951
|
+
addSystemMessage(`Failed to resume: ${err instanceof Error ? err.message : String(err)}`);
|
|
42952
|
+
}
|
|
42953
|
+
};
|
|
42954
|
+
onMount(() => {
|
|
42955
|
+
if (props.resumeSessionId) {
|
|
42956
|
+
resumeSession(props.resumeSessionId);
|
|
42957
|
+
}
|
|
42958
|
+
});
|
|
42959
|
+
process.on("SIGINT", () => gracefulExit());
|
|
42960
|
+
process.on("SIGTERM", () => gracefulExit());
|
|
42961
|
+
process.on("SIGHUP", () => gracefulExit());
|
|
42342
42962
|
process.on("SIGTSTP", () => {
|
|
42343
42963
|
process.once("SIGCONT", () => renderer.resume());
|
|
42344
42964
|
renderer.suspend();
|
|
42345
42965
|
});
|
|
42346
|
-
const gracefulExit = () => {
|
|
42966
|
+
const gracefulExit = async () => {
|
|
42967
|
+
await props.orchestrator.abortAll();
|
|
42347
42968
|
renderer.destroy();
|
|
42348
42969
|
const adapters = props.orchestrator.getAdapters();
|
|
42349
|
-
Promise.allSettled(adapters.map((a) => a.destroy()))
|
|
42970
|
+
Promise.allSettled(adapters.map((a) => a.destroy())).finally(() => {
|
|
42971
|
+
process.exit(0);
|
|
42972
|
+
});
|
|
42973
|
+
setTimeout(() => process.exit(0), 2000);
|
|
42350
42974
|
};
|
|
42351
42975
|
useKeyboard((key) => {
|
|
42352
42976
|
if (key.ctrl && key.name === "p") {
|
|
42353
42977
|
setShowAgents((v2) => !v2);
|
|
42354
42978
|
return;
|
|
42355
42979
|
}
|
|
42356
|
-
if (showAgents())
|
|
42980
|
+
if (showAgents() || showCancel() || showInfo())
|
|
42357
42981
|
return;
|
|
42982
|
+
if (key.name === "escape") {
|
|
42983
|
+
const active = agents.filter((a) => {
|
|
42984
|
+
const state = agentStates().get(a.name);
|
|
42985
|
+
return state && state !== "idle" && state !== "error";
|
|
42986
|
+
}).map((a) => a.name);
|
|
42987
|
+
if (active.length > 0) {
|
|
42988
|
+
setShowCancel(true);
|
|
42989
|
+
}
|
|
42990
|
+
return;
|
|
42991
|
+
}
|
|
42358
42992
|
if (key.ctrl && key.name === "c") {
|
|
42359
42993
|
if (!copySelection(renderer)) {
|
|
42360
42994
|
gracefulExit();
|
|
@@ -42425,6 +43059,19 @@ ${files.map((f) => ` ${f}`).join(`
|
|
|
42425
43059
|
setShowInfo(true);
|
|
42426
43060
|
return;
|
|
42427
43061
|
}
|
|
43062
|
+
if (line.startsWith("/resume")) {
|
|
43063
|
+
const sid = line.replace("/resume", "").trim();
|
|
43064
|
+
if (!sid) {
|
|
43065
|
+
addSystemMessage("Usage: /resume <sessionId>");
|
|
43066
|
+
return;
|
|
43067
|
+
}
|
|
43068
|
+
if (props.orchestrator.hasMessages()) {
|
|
43069
|
+
addSystemMessage("Resume only works before the first message.");
|
|
43070
|
+
return;
|
|
43071
|
+
}
|
|
43072
|
+
await resumeSession(sid);
|
|
43073
|
+
return;
|
|
43074
|
+
}
|
|
42428
43075
|
if (line.startsWith("/flood")) {
|
|
42429
43076
|
const args = line.split(/\s+/);
|
|
42430
43077
|
const count = parseInt(args[1], 10) || 50;
|
|
@@ -42489,16 +43136,19 @@ ${lines.join(`
|
|
|
42489
43136
|
},
|
|
42490
43137
|
get stickyTarget() {
|
|
42491
43138
|
return stickyTarget();
|
|
43139
|
+
},
|
|
43140
|
+
get queueCounts() {
|
|
43141
|
+
return queueCounts();
|
|
42492
43142
|
}
|
|
42493
43143
|
}), null);
|
|
42494
43144
|
insert(_el$, createComponent2(InputLine, {
|
|
42495
43145
|
humanName,
|
|
42496
43146
|
onSubmit: handleSubmit,
|
|
42497
43147
|
get disabled() {
|
|
42498
|
-
return
|
|
43148
|
+
return showAgents() || showInfo() || showCancel();
|
|
42499
43149
|
},
|
|
42500
43150
|
get disabledMessage() {
|
|
42501
|
-
return showAgents() ? "" : undefined;
|
|
43151
|
+
return showAgents() || showCancel() ? "" : undefined;
|
|
42502
43152
|
}
|
|
42503
43153
|
}), null);
|
|
42504
43154
|
insert(_el$, (() => {
|
|
@@ -42521,6 +43171,24 @@ ${lines.join(`
|
|
|
42521
43171
|
onClose: () => setShowInfo(false)
|
|
42522
43172
|
});
|
|
42523
43173
|
})(), null);
|
|
43174
|
+
insert(_el$, (() => {
|
|
43175
|
+
var _c$3 = memo2(() => !!showCancel());
|
|
43176
|
+
return () => _c$3() && createComponent2(CancelPanel, {
|
|
43177
|
+
get activeAgents() {
|
|
43178
|
+
return agents.filter((a) => {
|
|
43179
|
+
const state = agentStates().get(a.name);
|
|
43180
|
+
return state && state !== "idle" && state !== "error";
|
|
43181
|
+
}).map((a) => a.name);
|
|
43182
|
+
},
|
|
43183
|
+
onCancel: (names) => {
|
|
43184
|
+
props.orchestrator.cancelAgents(names);
|
|
43185
|
+
const label = names.length === agents.length ? "all agents" : names.join(", ");
|
|
43186
|
+
addSystemMessage(`Cancelled ${label}`);
|
|
43187
|
+
setShowCancel(false);
|
|
43188
|
+
},
|
|
43189
|
+
onClose: () => setShowCancel(false)
|
|
43190
|
+
});
|
|
43191
|
+
})(), null);
|
|
42524
43192
|
effect((_$p) => setProp(_el$3, "fg", COLORS.primary, _$p));
|
|
42525
43193
|
return _el$;
|
|
42526
43194
|
}
|
|
@@ -42531,6 +43199,8 @@ ${lines.join(`
|
|
|
42531
43199
|
async function main2() {
|
|
42532
43200
|
const appRoot = path11.resolve(path11.dirname(fileURLToPath3(import.meta.url)), "..");
|
|
42533
43201
|
await initLlmPartyHome(appRoot);
|
|
43202
|
+
const resumeIndex = process.argv.indexOf("--resume");
|
|
43203
|
+
const resumeSessionId = resumeIndex !== -1 ? process.argv[resumeIndex + 1] : undefined;
|
|
42534
43204
|
const rendererConfig = {
|
|
42535
43205
|
exitOnCtrlC: false,
|
|
42536
43206
|
useMouse: true,
|
|
@@ -42541,14 +43211,14 @@ async function main2() {
|
|
|
42541
43211
|
await render(() => ConfigWizard({
|
|
42542
43212
|
isFirstRun: true,
|
|
42543
43213
|
onComplete: async () => {
|
|
42544
|
-
await bootApp(appRoot, rendererConfig);
|
|
43214
|
+
await bootApp(appRoot, rendererConfig, resumeSessionId);
|
|
42545
43215
|
}
|
|
42546
43216
|
}), rendererConfig);
|
|
42547
43217
|
} else {
|
|
42548
|
-
await bootApp(appRoot, rendererConfig);
|
|
43218
|
+
await bootApp(appRoot, rendererConfig, resumeSessionId);
|
|
42549
43219
|
}
|
|
42550
43220
|
}
|
|
42551
|
-
async function bootApp(appRoot, rendererConfig) {
|
|
43221
|
+
async function bootApp(appRoot, rendererConfig, resumeSessionId) {
|
|
42552
43222
|
const configPath = await resolveConfigPath(appRoot);
|
|
42553
43223
|
const config = await loadConfig2(configPath);
|
|
42554
43224
|
const humanName = config.humanName?.trim() || "USER";
|
|
@@ -42594,7 +43264,7 @@ async function bootApp(appRoot, rendererConfig) {
|
|
|
42594
43264
|
const promptParts = [mergedBase];
|
|
42595
43265
|
if (agent.prompts && agent.prompts.length > 0) {
|
|
42596
43266
|
const extraPaths = agent.prompts.map((p) => resolveFromConfig(p));
|
|
42597
|
-
const extraParts = await Promise.all(extraPaths.map((p) =>
|
|
43267
|
+
const extraParts = await Promise.all(extraPaths.map((p) => readFile6(p, "utf8")));
|
|
42598
43268
|
promptParts.push(...extraParts);
|
|
42599
43269
|
}
|
|
42600
43270
|
const promptTemplate = promptParts.join(`
|
|
@@ -42638,8 +43308,8 @@ ${mySkills.map((s) => `- ${s}`).join(`
|
|
|
42638
43308
|
}));
|
|
42639
43309
|
const defaultTimeout = typeof config.timeout === "number" && config.timeout > 0 ? config.timeout * 1000 : 600000;
|
|
42640
43310
|
const agentTimeouts = Object.fromEntries(activeAgents.filter((agent) => typeof agent.timeout === "number" && agent.timeout > 0).map((agent) => [agent.name, agent.timeout * 1000]));
|
|
42641
|
-
const orchestrator = new Orchestrator(adapters, humanName, Object.fromEntries(activeAgents.map((agent) => [agent.name, agent.tag?.trim() || toTag(agent.name)])), humanTag, defaultTimeout, agentTimeouts, { reminderInterval: config.reminderInterval });
|
|
42642
|
-
await render(() => App({ orchestrator,
|
|
43311
|
+
const orchestrator = new Orchestrator(adapters, humanName, Object.fromEntries(activeAgents.map((agent) => [agent.name, agent.tag?.trim() || toTag(agent.name)])), humanTag, defaultTimeout, agentTimeouts, { reminderInterval: config.reminderInterval, maxAutoHops });
|
|
43312
|
+
await render(() => App({ orchestrator, config, configPath, resumeSessionId }), rendererConfig);
|
|
42643
43313
|
}
|
|
42644
43314
|
function resolveMaxAutoHops(value) {
|
|
42645
43315
|
if (typeof value === "number" && value === 0) {
|