llm-party-cli 0.1.2 → 0.2.1
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 +9 -6
- package/dist/index.js +1330 -138
- package/package.json +1 -1
- package/dist/adapters/base.js +0 -1
- package/dist/adapters/claude.js +0 -64
- package/dist/adapters/codex.js +0 -44
- package/dist/adapters/copilot.js +0 -46
- package/dist/adapters/glm.js +0 -91
- package/dist/config/loader.js +0 -131
- package/dist/orchestrator.js +0 -185
- package/dist/types.js +0 -1
- package/dist/ui/terminal.js +0 -219
package/dist/index.js
CHANGED
|
@@ -31304,9 +31304,9 @@ var require_main2 = __commonJS((exports) => {
|
|
|
31304
31304
|
|
|
31305
31305
|
// src/index.ts
|
|
31306
31306
|
var import_config = __toESM(require_config(), 1);
|
|
31307
|
-
var
|
|
31307
|
+
var import_react24 = __toESM(require_react(), 1);
|
|
31308
31308
|
import { readFile as readFile5 } from "fs/promises";
|
|
31309
|
-
import
|
|
31309
|
+
import path11 from "path";
|
|
31310
31310
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
31311
31311
|
|
|
31312
31312
|
// node_modules/@opentui/core/index-e89anq5x.js
|
|
@@ -73642,6 +73642,13 @@ function Eg({ prompt: Q2, options: X2 }) {
|
|
|
73642
73642
|
return d7;
|
|
73643
73643
|
}
|
|
73644
73644
|
|
|
73645
|
+
// src/adapters/base.ts
|
|
73646
|
+
function formatTranscript(messages) {
|
|
73647
|
+
return messages.map((m3) => `[${m3.from}]: ${m3.text}`).join(`
|
|
73648
|
+
|
|
73649
|
+
`);
|
|
73650
|
+
}
|
|
73651
|
+
|
|
73645
73652
|
// src/adapters/claude-base.ts
|
|
73646
73653
|
class ClaudeBaseAdapter {
|
|
73647
73654
|
name;
|
|
@@ -73663,10 +73670,7 @@ class ClaudeBaseAdapter {
|
|
|
73663
73670
|
return { ...process.env, ...config.env ?? {} };
|
|
73664
73671
|
}
|
|
73665
73672
|
async send(messages) {
|
|
73666
|
-
|
|
73667
|
-
|
|
73668
|
-
`);
|
|
73669
|
-
return await this.querySDK(transcript);
|
|
73673
|
+
return await this.querySDK(formatTranscript(messages));
|
|
73670
73674
|
}
|
|
73671
73675
|
async destroy() {
|
|
73672
73676
|
return;
|
|
@@ -74166,10 +74170,7 @@ class CodexAdapter {
|
|
|
74166
74170
|
if (!this.thread) {
|
|
74167
74171
|
return "[Codex thread not initialized]";
|
|
74168
74172
|
}
|
|
74169
|
-
const
|
|
74170
|
-
|
|
74171
|
-
`);
|
|
74172
|
-
const turn = await this.thread.run(transcript);
|
|
74173
|
+
const turn = await this.thread.run(formatTranscript(messages));
|
|
74173
74174
|
if (turn.finalResponse && turn.finalResponse.length > 0) {
|
|
74174
74175
|
return turn.finalResponse;
|
|
74175
74176
|
}
|
|
@@ -75372,9 +75373,7 @@ class CopilotAdapter {
|
|
|
75372
75373
|
if (!this.session) {
|
|
75373
75374
|
return "[Copilot session not initialized]";
|
|
75374
75375
|
}
|
|
75375
|
-
const transcript = messages
|
|
75376
|
-
|
|
75377
|
-
`);
|
|
75376
|
+
const transcript = formatTranscript(messages);
|
|
75378
75377
|
try {
|
|
75379
75378
|
return await this.sendToSession(transcript);
|
|
75380
75379
|
} catch (err) {
|
|
@@ -75490,7 +75489,59 @@ async function loadGlmAliasEnv() {
|
|
|
75490
75489
|
import { readFile as readFile3, writeFile as writeFile3, access, mkdir as mkdir3 } from "fs/promises";
|
|
75491
75490
|
import { homedir, userInfo } from "os";
|
|
75492
75491
|
import path8 from "path";
|
|
75493
|
-
|
|
75492
|
+
|
|
75493
|
+
// src/config/defaults.ts
|
|
75494
|
+
var PROVIDERS = [
|
|
75495
|
+
{
|
|
75496
|
+
id: "claude",
|
|
75497
|
+
displayName: "Claude",
|
|
75498
|
+
description: "Anthropic Claude Agent SDK",
|
|
75499
|
+
unavailableHint: "claude CLI not found",
|
|
75500
|
+
defaultModel: "sonnet",
|
|
75501
|
+
defaultTag: "claude",
|
|
75502
|
+
detectCommand: "claude",
|
|
75503
|
+
detectType: "binary"
|
|
75504
|
+
},
|
|
75505
|
+
{
|
|
75506
|
+
id: "codex",
|
|
75507
|
+
displayName: "Codex",
|
|
75508
|
+
description: "OpenAI Codex SDK",
|
|
75509
|
+
unavailableHint: "codex CLI not found",
|
|
75510
|
+
defaultModel: "gpt-5.2",
|
|
75511
|
+
defaultTag: "codex",
|
|
75512
|
+
detectCommand: "codex",
|
|
75513
|
+
detectType: "binary"
|
|
75514
|
+
},
|
|
75515
|
+
{
|
|
75516
|
+
id: "copilot",
|
|
75517
|
+
displayName: "Copilot",
|
|
75518
|
+
description: "GitHub Copilot SDK",
|
|
75519
|
+
unavailableHint: "copilot CLI not found",
|
|
75520
|
+
defaultModel: "gpt-4.1",
|
|
75521
|
+
defaultTag: "copilot",
|
|
75522
|
+
detectCommand: "copilot",
|
|
75523
|
+
detectType: "binary"
|
|
75524
|
+
},
|
|
75525
|
+
{
|
|
75526
|
+
id: "glm",
|
|
75527
|
+
displayName: "GLM",
|
|
75528
|
+
description: "glm alias configured on Claude Code CLI",
|
|
75529
|
+
unavailableHint: "glm shell alias not configured",
|
|
75530
|
+
defaultModel: "glm-5",
|
|
75531
|
+
defaultTag: "glm",
|
|
75532
|
+
detectCommand: "glm",
|
|
75533
|
+
detectType: "alias",
|
|
75534
|
+
env: {
|
|
75535
|
+
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
75536
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
|
75537
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.5",
|
|
75538
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5"
|
|
75539
|
+
}
|
|
75540
|
+
}
|
|
75541
|
+
];
|
|
75542
|
+
|
|
75543
|
+
// src/config/loader.ts
|
|
75544
|
+
var VALID_PROVIDER_IDS = new Set(PROVIDERS.map((p2) => p2.id));
|
|
75494
75545
|
var LLM_PARTY_HOME = path8.join(homedir(), ".llm-party");
|
|
75495
75546
|
function validateConfig(data) {
|
|
75496
75547
|
if (!data || typeof data !== "object") {
|
|
@@ -75520,8 +75571,8 @@ function validateConfig(data) {
|
|
|
75520
75571
|
if (typeof agent.model !== "string" || agent.model.trim() === "") {
|
|
75521
75572
|
throw new Error(`Agent '${agent.name}' must have a non-empty 'model' string`);
|
|
75522
75573
|
}
|
|
75523
|
-
if (!
|
|
75524
|
-
throw new Error(`Agent '${agent.name}' has invalid provider '${agent.provider}'. Valid: ${
|
|
75574
|
+
if (!VALID_PROVIDER_IDS.has(agent.provider)) {
|
|
75575
|
+
throw new Error(`Agent '${agent.name}' has invalid provider '${agent.provider}'. Valid: ${Array.from(VALID_PROVIDER_IDS).join(", ")}`);
|
|
75525
75576
|
}
|
|
75526
75577
|
if (agent.prompts !== undefined) {
|
|
75527
75578
|
const isArray = Array.isArray(agent.prompts) && agent.prompts.every((p2) => typeof p2 === "string");
|
|
@@ -75562,24 +75613,22 @@ async function resolveArtifactsPrompt(appRoot) {
|
|
|
75562
75613
|
const bundledArtifacts = path8.join(appRoot, "prompts", "artifacts.md");
|
|
75563
75614
|
return await readFile3(bundledArtifacts, "utf8");
|
|
75564
75615
|
}
|
|
75616
|
+
async function ensureFile(filePath, defaultContent) {
|
|
75617
|
+
try {
|
|
75618
|
+
await access(filePath);
|
|
75619
|
+
} catch {
|
|
75620
|
+
await writeFile3(filePath, defaultContent, "utf8");
|
|
75621
|
+
}
|
|
75622
|
+
}
|
|
75565
75623
|
async function initProjectFolder(cwd) {
|
|
75566
75624
|
const projectHome = path8.join(cwd, ".llm-party");
|
|
75567
75625
|
const memoryDir = path8.join(projectHome, "memory");
|
|
75568
75626
|
const skillsDir = path8.join(projectHome, "skills");
|
|
75569
75627
|
await mkdir3(memoryDir, { recursive: true });
|
|
75570
75628
|
await mkdir3(skillsDir, { recursive: true });
|
|
75571
|
-
|
|
75572
|
-
|
|
75573
|
-
|
|
75574
|
-
} catch {
|
|
75575
|
-
await writeFile3(tasksFile, `# Tasks
|
|
75576
|
-
`, "utf8");
|
|
75577
|
-
}
|
|
75578
|
-
const projectMd = path8.join(memoryDir, "project.md");
|
|
75579
|
-
try {
|
|
75580
|
-
await access(projectMd);
|
|
75581
|
-
} catch {
|
|
75582
|
-
await writeFile3(projectMd, `# Project Memory
|
|
75629
|
+
await ensureFile(path8.join(projectHome, "TASKS.md"), `# Tasks
|
|
75630
|
+
`);
|
|
75631
|
+
await ensureFile(path8.join(memoryDir, "project.md"), `# Project Memory
|
|
75583
75632
|
|
|
75584
75633
|
## Current State
|
|
75585
75634
|
|
|
@@ -75591,41 +75640,26 @@ Next:
|
|
|
75591
75640
|
---
|
|
75592
75641
|
|
|
75593
75642
|
## Log
|
|
75594
|
-
|
|
75595
|
-
|
|
75596
|
-
|
|
75597
|
-
try {
|
|
75598
|
-
await access(decisionsMd);
|
|
75599
|
-
} catch {
|
|
75600
|
-
await writeFile3(decisionsMd, `# Decisions
|
|
75601
|
-
`, "utf8");
|
|
75602
|
-
}
|
|
75643
|
+
`);
|
|
75644
|
+
await ensureFile(path8.join(memoryDir, "decisions.md"), `# Decisions
|
|
75645
|
+
`);
|
|
75603
75646
|
}
|
|
75604
75647
|
async function initLlmPartyHome(appRoot) {
|
|
75605
75648
|
await mkdir3(LLM_PARTY_HOME, { recursive: true });
|
|
75606
75649
|
await mkdir3(path8.join(LLM_PARTY_HOME, "sessions"), { recursive: true });
|
|
75607
75650
|
await mkdir3(path8.join(LLM_PARTY_HOME, "network"), { recursive: true });
|
|
75608
75651
|
await mkdir3(path8.join(LLM_PARTY_HOME, "agents"), { recursive: true });
|
|
75609
|
-
|
|
75610
|
-
|
|
75611
|
-
|
|
75612
|
-
|
|
75613
|
-
|
|
75614
|
-
|
|
75615
|
-
}
|
|
75616
|
-
const librariesYml = path8.join(LLM_PARTY_HOME, "network", "libraries.yml");
|
|
75617
|
-
try {
|
|
75618
|
-
await access(librariesYml);
|
|
75619
|
-
} catch {
|
|
75620
|
-
await writeFile3(librariesYml, `libraries: []
|
|
75621
|
-
`, "utf8");
|
|
75622
|
-
}
|
|
75623
|
-
const globalConfig = path8.join(LLM_PARTY_HOME, "config.json");
|
|
75652
|
+
await ensureFile(path8.join(LLM_PARTY_HOME, "network", "projects.yml"), `projects: []
|
|
75653
|
+
`);
|
|
75654
|
+
await ensureFile(path8.join(LLM_PARTY_HOME, "network", "libraries.yml"), `libraries: []
|
|
75655
|
+
`);
|
|
75656
|
+
}
|
|
75657
|
+
async function configExists() {
|
|
75624
75658
|
try {
|
|
75625
|
-
await access(
|
|
75659
|
+
await access(path8.join(LLM_PARTY_HOME, "config.json"));
|
|
75660
|
+
return true;
|
|
75626
75661
|
} catch {
|
|
75627
|
-
|
|
75628
|
-
await writeFile3(globalConfig, bundledConfig, "utf8");
|
|
75662
|
+
return false;
|
|
75629
75663
|
}
|
|
75630
75664
|
}
|
|
75631
75665
|
async function loadConfig2(configPath) {
|
|
@@ -75826,8 +75860,8 @@ function createSessionId() {
|
|
|
75826
75860
|
}
|
|
75827
75861
|
|
|
75828
75862
|
// src/ui/App.tsx
|
|
75829
|
-
var
|
|
75830
|
-
import { spawn as
|
|
75863
|
+
var import_react22 = __toESM(require_react(), 1);
|
|
75864
|
+
import { spawn as spawn5 } from "child_process";
|
|
75831
75865
|
|
|
75832
75866
|
// src/ui/useOrchestrator.ts
|
|
75833
75867
|
var import_react13 = __toESM(require_react(), 1);
|
|
@@ -75843,7 +75877,6 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
75843
75877
|
const [stickyTarget, setStickyTarget] = import_react13.useState(undefined);
|
|
75844
75878
|
const [dispatching, setDispatching] = import_react13.useState(false);
|
|
75845
75879
|
const projectFolderReady = import_react13.useRef(false);
|
|
75846
|
-
const knownChangedFiles = import_react13.useRef([]);
|
|
75847
75880
|
const agentProviders = import_react13.useRef(new Map(orchestrator.listAgents().map((a2) => [a2.name.toUpperCase(), a2.provider])));
|
|
75848
75881
|
const dispatch = import_react13.useCallback(async (line) => {
|
|
75849
75882
|
if (!line.trim())
|
|
@@ -75872,7 +75905,7 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
75872
75905
|
setMessages((prev) => [...prev, userDisplay]);
|
|
75873
75906
|
setDispatching(true);
|
|
75874
75907
|
try {
|
|
75875
|
-
await dispatchWithHandoffs(orchestrator, targets, maxAutoHops,
|
|
75908
|
+
await dispatchWithHandoffs(orchestrator, targets, maxAutoHops, agentProviders.current, setMessages, setAgentStates);
|
|
75876
75909
|
} finally {
|
|
75877
75910
|
setDispatching(false);
|
|
75878
75911
|
}
|
|
@@ -75892,7 +75925,7 @@ function useOrchestrator(orchestrator, maxAutoHops) {
|
|
|
75892
75925
|
}, []);
|
|
75893
75926
|
return { messages, agentStates, stickyTarget, dispatching, dispatch, addSystemMessage, clearMessages };
|
|
75894
75927
|
}
|
|
75895
|
-
async function dispatchWithHandoffs(orchestrator, initialTargets, maxHops,
|
|
75928
|
+
async function dispatchWithHandoffs(orchestrator, initialTargets, maxHops, agentProviders, setMessages, setAgentStates) {
|
|
75896
75929
|
let targets = initialTargets;
|
|
75897
75930
|
let hops = 0;
|
|
75898
75931
|
while (true) {
|
|
@@ -75931,21 +75964,6 @@ async function dispatchWithHandoffs(orchestrator, initialTargets, maxHops, known
|
|
|
75931
75964
|
}
|
|
75932
75965
|
return next;
|
|
75933
75966
|
});
|
|
75934
|
-
const latestChangedFiles = await getChangedFiles();
|
|
75935
|
-
const newlyChanged = diffFiles(knownChangedFilesRef.current, latestChangedFiles);
|
|
75936
|
-
if (newlyChanged.length > 0) {
|
|
75937
|
-
const systemMsg = {
|
|
75938
|
-
id: nextSystemId(),
|
|
75939
|
-
from: "SYSTEM",
|
|
75940
|
-
text: `Files modified:
|
|
75941
|
-
${newlyChanged.map((f) => ` ${f}`).join(`
|
|
75942
|
-
`)}`,
|
|
75943
|
-
createdAt: new Date().toISOString(),
|
|
75944
|
-
type: "system"
|
|
75945
|
-
};
|
|
75946
|
-
setMessages((prev) => [...prev, systemMsg]);
|
|
75947
|
-
}
|
|
75948
|
-
knownChangedFilesRef.current = latestChangedFiles;
|
|
75949
75967
|
const nextSelectors = extractNextSelectors(batch);
|
|
75950
75968
|
if (nextSelectors.length === 0)
|
|
75951
75969
|
return;
|
|
@@ -75996,10 +76014,6 @@ function getChangedFiles() {
|
|
|
75996
76014
|
});
|
|
75997
76015
|
});
|
|
75998
76016
|
}
|
|
75999
|
-
function diffFiles(before, after) {
|
|
76000
|
-
const set = new Set(before);
|
|
76001
|
-
return after.filter((f) => !set.has(f));
|
|
76002
|
-
}
|
|
76003
76017
|
function extractNextSelectors(messages) {
|
|
76004
76018
|
const selectors = [];
|
|
76005
76019
|
for (const msg of messages) {
|
|
@@ -76025,6 +76039,33 @@ function parseRouting(line) {
|
|
|
76025
76039
|
return { mentions, raw: line };
|
|
76026
76040
|
}
|
|
76027
76041
|
|
|
76042
|
+
// src/ui/theme.ts
|
|
76043
|
+
var COLORS = {
|
|
76044
|
+
primary: "#00BFFF",
|
|
76045
|
+
success: "#00FF88",
|
|
76046
|
+
human: "#00FF00",
|
|
76047
|
+
agent: "#FF00FF",
|
|
76048
|
+
error: "#FF4444",
|
|
76049
|
+
warning: "#FF8800",
|
|
76050
|
+
textPrimary: "#FFFFFF",
|
|
76051
|
+
textSecondary: "#AAAAAA",
|
|
76052
|
+
textMuted: "#888888",
|
|
76053
|
+
textDim: "#666666",
|
|
76054
|
+
textSubtle: "#555555",
|
|
76055
|
+
textFaint: "#444444",
|
|
76056
|
+
borderActive: "#00FF00",
|
|
76057
|
+
borderDim: "#555555",
|
|
76058
|
+
borderStrong: "#333333",
|
|
76059
|
+
bgPanel: "#0d0d1a",
|
|
76060
|
+
bgContent: "#111122",
|
|
76061
|
+
bgFocus: "#1a1a2e",
|
|
76062
|
+
bgActiveTab: "#1a2a1a",
|
|
76063
|
+
bgError: "#1a0000",
|
|
76064
|
+
bgSweepDim: "#1a1a1a",
|
|
76065
|
+
bgSweepLow: "#333333"
|
|
76066
|
+
};
|
|
76067
|
+
var PARTY_COLORS = [COLORS.agent, COLORS.success, COLORS.primary, "#FFE000"];
|
|
76068
|
+
|
|
76028
76069
|
// node_modules/@opentui/react/jsx-dev-runtime.js
|
|
76029
76070
|
var import_jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
76030
76071
|
|
|
@@ -76032,7 +76073,7 @@ var import_jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
|
76032
76073
|
function MessageBubble({ message, humanName }) {
|
|
76033
76074
|
if (message.type === "system") {
|
|
76034
76075
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76035
|
-
fg:
|
|
76076
|
+
fg: COLORS.textDim,
|
|
76036
76077
|
selectable: true,
|
|
76037
76078
|
children: message.text
|
|
76038
76079
|
}, undefined, false, undefined, this);
|
|
@@ -76042,7 +76083,7 @@ function MessageBubble({ message, humanName }) {
|
|
|
76042
76083
|
selectable: true,
|
|
76043
76084
|
children: [
|
|
76044
76085
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76045
|
-
fg:
|
|
76086
|
+
fg: COLORS.human,
|
|
76046
76087
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
76047
76088
|
children: [
|
|
76048
76089
|
"[",
|
|
@@ -76064,7 +76105,7 @@ function MessageBubble({ message, humanName }) {
|
|
|
76064
76105
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76065
76106
|
selectable: true,
|
|
76066
76107
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76067
|
-
fg:
|
|
76108
|
+
fg: COLORS.agent,
|
|
76068
76109
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
76069
76110
|
children: [
|
|
76070
76111
|
"[",
|
|
@@ -76084,7 +76125,11 @@ function MessageBubble({ message, humanName }) {
|
|
|
76084
76125
|
|
|
76085
76126
|
// src/ui/StatusBar.tsx
|
|
76086
76127
|
var import_react14 = __toESM(require_react(), 1);
|
|
76087
|
-
|
|
76128
|
+
|
|
76129
|
+
// src/ui/constants.ts
|
|
76130
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
76131
|
+
|
|
76132
|
+
// src/ui/StatusBar.tsx
|
|
76088
76133
|
var PULSE_COLORS = ["#005F87", "#0087AF", "#00AFD7", "#00D7FF", "#5FF", "#00D7FF", "#0087AF"];
|
|
76089
76134
|
function useThinkingAnimation(active) {
|
|
76090
76135
|
const [frame, setFrame] = import_react14.useState(0);
|
|
@@ -76094,13 +76139,13 @@ function useThinkingAnimation(active) {
|
|
|
76094
76139
|
return;
|
|
76095
76140
|
}
|
|
76096
76141
|
const interval = setInterval(() => {
|
|
76097
|
-
setFrame((f) => (f + 1) % (
|
|
76142
|
+
setFrame((f) => (f + 1) % (SPINNER_FRAMES.length * PULSE_COLORS.length));
|
|
76098
76143
|
}, 80);
|
|
76099
76144
|
return () => clearInterval(interval);
|
|
76100
76145
|
}, [active]);
|
|
76101
76146
|
return {
|
|
76102
|
-
spinner: active ?
|
|
76103
|
-
color: active ? PULSE_COLORS[frame % PULSE_COLORS.length] :
|
|
76147
|
+
spinner: active ? SPINNER_FRAMES[frame % SPINNER_FRAMES.length] : "",
|
|
76148
|
+
color: active ? PULSE_COLORS[frame % PULSE_COLORS.length] : COLORS.textMuted
|
|
76104
76149
|
};
|
|
76105
76150
|
}
|
|
76106
76151
|
function StatusBar({ agents, agentStates, sessionId, stickyTarget }) {
|
|
@@ -76118,15 +76163,15 @@ function StatusBar({ agents, agentStates, sessionId, stickyTarget }) {
|
|
|
76118
76163
|
gap: 2,
|
|
76119
76164
|
children: [
|
|
76120
76165
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76121
|
-
fg:
|
|
76166
|
+
fg: COLORS.textMuted,
|
|
76122
76167
|
children: target
|
|
76123
76168
|
}, undefined, false, undefined, this),
|
|
76124
76169
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76125
|
-
fg:
|
|
76170
|
+
fg: COLORS.textSubtle,
|
|
76126
76171
|
children: "|"
|
|
76127
76172
|
}, undefined, false, undefined, this),
|
|
76128
76173
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76129
|
-
fg:
|
|
76174
|
+
fg: COLORS.textDim,
|
|
76130
76175
|
children: sessionId.slice(0, 20)
|
|
76131
76176
|
}, undefined, false, undefined, this)
|
|
76132
76177
|
]
|
|
@@ -76147,7 +76192,7 @@ function AgentChip({ name, state }) {
|
|
|
76147
76192
|
const { spinner, color } = useThinkingAnimation(state === "thinking");
|
|
76148
76193
|
if (state === "error") {
|
|
76149
76194
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76150
|
-
fg:
|
|
76195
|
+
fg: COLORS.error,
|
|
76151
76196
|
children: [
|
|
76152
76197
|
name,
|
|
76153
76198
|
" ERR"
|
|
@@ -76165,7 +76210,7 @@ function AgentChip({ name, state }) {
|
|
|
76165
76210
|
}, undefined, true, undefined, this);
|
|
76166
76211
|
}
|
|
76167
76212
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76168
|
-
fg:
|
|
76213
|
+
fg: COLORS.textMuted,
|
|
76169
76214
|
children: name
|
|
76170
76215
|
}, undefined, false, undefined, this);
|
|
76171
76216
|
}
|
|
@@ -76186,7 +76231,7 @@ var FUNCTION_KEYS = new Set([
|
|
|
76186
76231
|
"f11",
|
|
76187
76232
|
"f12"
|
|
76188
76233
|
]);
|
|
76189
|
-
function InputLine({ humanName, onSubmit, disabled }) {
|
|
76234
|
+
function InputLine({ humanName, onSubmit, disabled, disabledMessage }) {
|
|
76190
76235
|
const valueRef = import_react15.useRef("");
|
|
76191
76236
|
const cursorRef = import_react15.useRef(0);
|
|
76192
76237
|
const [, forceRender] = import_react15.useState(0);
|
|
@@ -76337,10 +76382,11 @@ function InputLine({ humanName, onSubmit, disabled }) {
|
|
|
76337
76382
|
});
|
|
76338
76383
|
const value = valueRef.current;
|
|
76339
76384
|
const cursor = cursorRef.current;
|
|
76340
|
-
const borderColor = disabled ?
|
|
76385
|
+
const borderColor = disabled ? COLORS.borderDim : COLORS.borderActive;
|
|
76341
76386
|
const label = `${humanName} > `;
|
|
76342
76387
|
const separator = "\u2500".repeat(Math.max(0, termWidth - 2));
|
|
76343
76388
|
if (disabled) {
|
|
76389
|
+
const msg = disabledMessage !== undefined ? disabledMessage : "waiting for agents...";
|
|
76344
76390
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
76345
76391
|
flexDirection: "column",
|
|
76346
76392
|
paddingX: 1,
|
|
@@ -76351,13 +76397,16 @@ function InputLine({ humanName, onSubmit, disabled }) {
|
|
|
76351
76397
|
fg: borderColor,
|
|
76352
76398
|
children: separator
|
|
76353
76399
|
}, undefined, false, undefined, this),
|
|
76354
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76355
|
-
fg:
|
|
76400
|
+
msg ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76401
|
+
fg: COLORS.textDim,
|
|
76356
76402
|
children: [
|
|
76357
76403
|
label,
|
|
76358
|
-
|
|
76404
|
+
msg
|
|
76359
76405
|
]
|
|
76360
|
-
}, undefined, true, undefined, this)
|
|
76406
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76407
|
+
fg: COLORS.textDim,
|
|
76408
|
+
children: label
|
|
76409
|
+
}, undefined, false, undefined, this)
|
|
76361
76410
|
]
|
|
76362
76411
|
}, undefined, true, undefined, this);
|
|
76363
76412
|
}
|
|
@@ -76375,18 +76424,18 @@ function InputLine({ humanName, onSubmit, disabled }) {
|
|
|
76375
76424
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76376
76425
|
children: [
|
|
76377
76426
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76378
|
-
fg:
|
|
76427
|
+
fg: COLORS.human,
|
|
76379
76428
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
76380
76429
|
children: label
|
|
76381
76430
|
}, undefined, false, undefined, this)
|
|
76382
76431
|
}, undefined, false, undefined, this),
|
|
76383
76432
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76384
|
-
bg:
|
|
76433
|
+
bg: COLORS.textPrimary,
|
|
76385
76434
|
fg: "#000000",
|
|
76386
76435
|
children: " "
|
|
76387
76436
|
}, undefined, false, undefined, this),
|
|
76388
76437
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76389
|
-
fg:
|
|
76438
|
+
fg: COLORS.textFaint,
|
|
76390
76439
|
children: " Type a message or /command..."
|
|
76391
76440
|
}, undefined, false, undefined, this)
|
|
76392
76441
|
]
|
|
@@ -76410,14 +76459,14 @@ function InputLine({ humanName, onSubmit, disabled }) {
|
|
|
76410
76459
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76411
76460
|
children: [
|
|
76412
76461
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76413
|
-
fg:
|
|
76462
|
+
fg: COLORS.human,
|
|
76414
76463
|
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
76415
76464
|
children: label
|
|
76416
76465
|
}, undefined, false, undefined, this)
|
|
76417
76466
|
}, undefined, false, undefined, this),
|
|
76418
76467
|
before,
|
|
76419
76468
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76420
|
-
bg:
|
|
76469
|
+
bg: COLORS.textPrimary,
|
|
76421
76470
|
fg: "#000000",
|
|
76422
76471
|
children: cursorChar
|
|
76423
76472
|
}, undefined, false, undefined, this),
|
|
@@ -76428,9 +76477,1120 @@ function InputLine({ humanName, onSubmit, disabled }) {
|
|
|
76428
76477
|
}, undefined, true, undefined, this);
|
|
76429
76478
|
}
|
|
76430
76479
|
|
|
76480
|
+
// src/ui/ConfigWizard.tsx
|
|
76481
|
+
var import_react19 = __toESM(require_react(), 1);
|
|
76482
|
+
import { userInfo as userInfo3 } from "os";
|
|
76483
|
+
|
|
76484
|
+
// src/config/detector.ts
|
|
76485
|
+
import { spawn as spawn4 } from "child_process";
|
|
76486
|
+
var DETECT_TIMEOUT = 5000;
|
|
76487
|
+
function detectBinary(command) {
|
|
76488
|
+
return new Promise((resolve4) => {
|
|
76489
|
+
const timer = setTimeout(() => resolve4({ available: false }), DETECT_TIMEOUT);
|
|
76490
|
+
const proc = spawn4(command, ["--version"], {
|
|
76491
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
76492
|
+
shell: true,
|
|
76493
|
+
timeout: DETECT_TIMEOUT
|
|
76494
|
+
});
|
|
76495
|
+
let output = "";
|
|
76496
|
+
proc.stdout?.on("data", (chunk) => {
|
|
76497
|
+
output += chunk.toString();
|
|
76498
|
+
});
|
|
76499
|
+
proc.on("close", (code) => {
|
|
76500
|
+
clearTimeout(timer);
|
|
76501
|
+
resolve4({
|
|
76502
|
+
available: code === 0,
|
|
76503
|
+
version: code === 0 ? output.trim().split(`
|
|
76504
|
+
`)[0] : undefined
|
|
76505
|
+
});
|
|
76506
|
+
});
|
|
76507
|
+
proc.on("error", () => {
|
|
76508
|
+
clearTimeout(timer);
|
|
76509
|
+
resolve4({ available: false });
|
|
76510
|
+
});
|
|
76511
|
+
});
|
|
76512
|
+
}
|
|
76513
|
+
function detectAlias(command) {
|
|
76514
|
+
return new Promise((resolve4) => {
|
|
76515
|
+
const shell = process.env.SHELL || "/bin/bash";
|
|
76516
|
+
const timer = setTimeout(() => resolve4({ available: false }), DETECT_TIMEOUT);
|
|
76517
|
+
const proc = spawn4(shell, ["-ic", `type ${command}`], {
|
|
76518
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
76519
|
+
timeout: DETECT_TIMEOUT
|
|
76520
|
+
});
|
|
76521
|
+
proc.on("close", (code) => {
|
|
76522
|
+
clearTimeout(timer);
|
|
76523
|
+
resolve4({ available: code === 0 });
|
|
76524
|
+
});
|
|
76525
|
+
proc.on("error", () => {
|
|
76526
|
+
clearTimeout(timer);
|
|
76527
|
+
resolve4({ available: false });
|
|
76528
|
+
});
|
|
76529
|
+
});
|
|
76530
|
+
}
|
|
76531
|
+
async function detectProviders() {
|
|
76532
|
+
const results = await Promise.allSettled(PROVIDERS.map(async (provider) => {
|
|
76533
|
+
const result = provider.detectType === "alias" ? await detectAlias(provider.detectCommand) : await detectBinary(provider.detectCommand);
|
|
76534
|
+
return {
|
|
76535
|
+
id: provider.id,
|
|
76536
|
+
available: result.available,
|
|
76537
|
+
version: "version" in result ? result.version : undefined
|
|
76538
|
+
};
|
|
76539
|
+
}));
|
|
76540
|
+
return results.map((result, i2) => {
|
|
76541
|
+
if (result.status === "fulfilled")
|
|
76542
|
+
return result.value;
|
|
76543
|
+
return { id: PROVIDERS[i2].id, available: false };
|
|
76544
|
+
});
|
|
76545
|
+
}
|
|
76546
|
+
|
|
76547
|
+
// src/config/writer.ts
|
|
76548
|
+
import { writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
|
|
76549
|
+
import { userInfo as userInfo2 } from "os";
|
|
76550
|
+
import path10 from "path";
|
|
76551
|
+
async function writeWizardConfig(selectedIds, overrides, existingConfig) {
|
|
76552
|
+
const overrideMap = new Map((overrides || []).map((o) => [o.id, o]));
|
|
76553
|
+
const existingByProvider = new Map;
|
|
76554
|
+
if (existingConfig?.agents) {
|
|
76555
|
+
for (const agent of existingConfig.agents) {
|
|
76556
|
+
existingByProvider.set(agent.provider, agent);
|
|
76557
|
+
}
|
|
76558
|
+
}
|
|
76559
|
+
const agents = selectedIds.map((id) => {
|
|
76560
|
+
const def = PROVIDERS.find((p2) => p2.id === id);
|
|
76561
|
+
if (!def)
|
|
76562
|
+
throw new Error(`Unknown provider: ${id}`);
|
|
76563
|
+
const override = overrideMap.get(id);
|
|
76564
|
+
const existing = existingByProvider.get(id);
|
|
76565
|
+
const agent = {
|
|
76566
|
+
name: override?.name || def.displayName,
|
|
76567
|
+
tag: override?.tag || def.defaultTag,
|
|
76568
|
+
provider: def.id,
|
|
76569
|
+
model: override?.model || def.defaultModel
|
|
76570
|
+
};
|
|
76571
|
+
if (existing?.env) {
|
|
76572
|
+
agent.env = { ...existing.env };
|
|
76573
|
+
} else if (def.env) {
|
|
76574
|
+
agent.env = { ...def.env };
|
|
76575
|
+
}
|
|
76576
|
+
if (existing?.prompts)
|
|
76577
|
+
agent.prompts = existing.prompts;
|
|
76578
|
+
if (existing?.executablePath)
|
|
76579
|
+
agent.executablePath = existing.executablePath;
|
|
76580
|
+
if (existing?.timeout)
|
|
76581
|
+
agent.timeout = existing.timeout;
|
|
76582
|
+
return agent;
|
|
76583
|
+
});
|
|
76584
|
+
const config = {
|
|
76585
|
+
humanName: existingConfig?.humanName || userInfo2().username || "USER",
|
|
76586
|
+
humanTag: existingConfig?.humanTag,
|
|
76587
|
+
maxAutoHops: existingConfig?.maxAutoHops ?? 15,
|
|
76588
|
+
timeout: existingConfig?.timeout,
|
|
76589
|
+
agents
|
|
76590
|
+
};
|
|
76591
|
+
if (!config.humanTag)
|
|
76592
|
+
delete config.humanTag;
|
|
76593
|
+
if (config.timeout === undefined)
|
|
76594
|
+
delete config.timeout;
|
|
76595
|
+
await mkdir6(LLM_PARTY_HOME, { recursive: true });
|
|
76596
|
+
const configPath = path10.join(LLM_PARTY_HOME, "config.json");
|
|
76597
|
+
await writeFile6(configPath, JSON.stringify(config, null, 2) + `
|
|
76598
|
+
`, "utf8");
|
|
76599
|
+
return configPath;
|
|
76600
|
+
}
|
|
76601
|
+
|
|
76602
|
+
// src/ui/MultiSelect.tsx
|
|
76603
|
+
var import_react17 = __toESM(require_react(), 1);
|
|
76604
|
+
function MultiSelect({ items, onConfirm, onCancel, initialSelected }) {
|
|
76605
|
+
const [focused, setFocused] = import_react17.useState(() => {
|
|
76606
|
+
return items.findIndex((item) => !item.disabled);
|
|
76607
|
+
});
|
|
76608
|
+
const [selected, setSelected] = import_react17.useState(() => {
|
|
76609
|
+
return new Set(initialSelected || []);
|
|
76610
|
+
});
|
|
76611
|
+
const [error, setError] = import_react17.useState("");
|
|
76612
|
+
const findNextEnabled = import_react17.useCallback((from, direction) => {
|
|
76613
|
+
let idx = from;
|
|
76614
|
+
for (let i2 = 0;i2 < items.length; i2++) {
|
|
76615
|
+
idx = (idx + direction + items.length) % items.length;
|
|
76616
|
+
if (!items[idx].disabled)
|
|
76617
|
+
return idx;
|
|
76618
|
+
}
|
|
76619
|
+
return from;
|
|
76620
|
+
}, [items]);
|
|
76621
|
+
useKeyboard((key) => {
|
|
76622
|
+
if (key.name === "up" || key.name === "k") {
|
|
76623
|
+
setFocused((f) => findNextEnabled(f, -1));
|
|
76624
|
+
setError("");
|
|
76625
|
+
return;
|
|
76626
|
+
}
|
|
76627
|
+
if (key.name === "down" || key.name === "j") {
|
|
76628
|
+
setFocused((f) => findNextEnabled(f, 1));
|
|
76629
|
+
setError("");
|
|
76630
|
+
return;
|
|
76631
|
+
}
|
|
76632
|
+
if (key.name === "space" || key.sequence === " ") {
|
|
76633
|
+
if (focused >= 0 && !items[focused].disabled) {
|
|
76634
|
+
setSelected((prev) => {
|
|
76635
|
+
const next = new Set(prev);
|
|
76636
|
+
if (next.has(focused)) {
|
|
76637
|
+
next.delete(focused);
|
|
76638
|
+
} else {
|
|
76639
|
+
next.add(focused);
|
|
76640
|
+
}
|
|
76641
|
+
return next;
|
|
76642
|
+
});
|
|
76643
|
+
setError("");
|
|
76644
|
+
}
|
|
76645
|
+
return;
|
|
76646
|
+
}
|
|
76647
|
+
if (key.name === "enter" || key.name === "return") {
|
|
76648
|
+
if (selected.size === 0) {
|
|
76649
|
+
setError("Select at least one agent");
|
|
76650
|
+
return;
|
|
76651
|
+
}
|
|
76652
|
+
onConfirm(Array.from(selected).sort((a2, b3) => a2 - b3));
|
|
76653
|
+
return;
|
|
76654
|
+
}
|
|
76655
|
+
if (key.name === "escape" && onCancel) {
|
|
76656
|
+
onCancel();
|
|
76657
|
+
return;
|
|
76658
|
+
}
|
|
76659
|
+
});
|
|
76660
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
76661
|
+
flexDirection: "column",
|
|
76662
|
+
children: [
|
|
76663
|
+
items.map((item, i2) => {
|
|
76664
|
+
const isSelected = selected.has(i2);
|
|
76665
|
+
const isFocused = i2 === focused;
|
|
76666
|
+
const isDisabled = !!item.disabled;
|
|
76667
|
+
const bullet = isSelected ? "\u25CF" : "\u25CB";
|
|
76668
|
+
const bulletColor = isDisabled ? COLORS.textFaint : isSelected ? COLORS.success : COLORS.textSecondary;
|
|
76669
|
+
const labelColor = isDisabled ? COLORS.textSubtle : COLORS.textPrimary;
|
|
76670
|
+
const descColor = isDisabled ? COLORS.textFaint : COLORS.textMuted;
|
|
76671
|
+
const bgColor = isFocused && !isDisabled ? COLORS.bgFocus : undefined;
|
|
76672
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76673
|
+
bg: bgColor,
|
|
76674
|
+
selectable: false,
|
|
76675
|
+
children: [
|
|
76676
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76677
|
+
fg: bulletColor,
|
|
76678
|
+
children: [
|
|
76679
|
+
" ",
|
|
76680
|
+
bullet,
|
|
76681
|
+
" "
|
|
76682
|
+
]
|
|
76683
|
+
}, undefined, true, undefined, this),
|
|
76684
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76685
|
+
fg: labelColor,
|
|
76686
|
+
children: item.label
|
|
76687
|
+
}, undefined, false, undefined, this),
|
|
76688
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76689
|
+
fg: descColor,
|
|
76690
|
+
children: [
|
|
76691
|
+
" ",
|
|
76692
|
+
item.description
|
|
76693
|
+
]
|
|
76694
|
+
}, undefined, true, undefined, this)
|
|
76695
|
+
]
|
|
76696
|
+
}, i2, true, undefined, this);
|
|
76697
|
+
}),
|
|
76698
|
+
error && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76699
|
+
fg: COLORS.error,
|
|
76700
|
+
marginTop: 1,
|
|
76701
|
+
children: [
|
|
76702
|
+
" ",
|
|
76703
|
+
error
|
|
76704
|
+
]
|
|
76705
|
+
}, undefined, true, undefined, this)
|
|
76706
|
+
]
|
|
76707
|
+
}, undefined, true, undefined, this);
|
|
76708
|
+
}
|
|
76709
|
+
|
|
76710
|
+
// src/ui/ConfigWizard.tsx
|
|
76711
|
+
var TAG_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
76712
|
+
function useSpinner() {
|
|
76713
|
+
const [frame, setFrame] = import_react19.useState(0);
|
|
76714
|
+
import_react19.useEffect(() => {
|
|
76715
|
+
const interval = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);
|
|
76716
|
+
return () => clearInterval(interval);
|
|
76717
|
+
}, []);
|
|
76718
|
+
return SPINNER_FRAMES[frame];
|
|
76719
|
+
}
|
|
76720
|
+
var SWEEP_CHARS = ["\u2591", "\u2592", "\u2593", "\u2588", "\u2593", "\u2592", "\u2591"];
|
|
76721
|
+
var BAR_WIDTH = 6;
|
|
76722
|
+
function SweepBar({ title }) {
|
|
76723
|
+
const glow = SWEEP_CHARS.length;
|
|
76724
|
+
const totalWidth = BAR_WIDTH * 2 + title.length + 2;
|
|
76725
|
+
const [pos, setPos] = import_react19.useState(0);
|
|
76726
|
+
import_react19.useEffect(() => {
|
|
76727
|
+
const interval = setInterval(() => setPos((p2) => (p2 + 1) % (BAR_WIDTH + glow)), 50);
|
|
76728
|
+
return () => clearInterval(interval);
|
|
76729
|
+
}, []);
|
|
76730
|
+
function buildSide(reverse2) {
|
|
76731
|
+
const spans = [];
|
|
76732
|
+
for (let i2 = 0;i2 < BAR_WIDTH; i2++) {
|
|
76733
|
+
const idx = reverse2 ? BAR_WIDTH - 1 - i2 : i2;
|
|
76734
|
+
const dist = idx - pos;
|
|
76735
|
+
if (dist >= 0 && dist < glow) {
|
|
76736
|
+
const colorIdx = Math.floor((pos + idx) / 2) % PARTY_COLORS.length;
|
|
76737
|
+
const intensity = 1 - Math.abs(dist - 3) / 3;
|
|
76738
|
+
spans.push({
|
|
76739
|
+
char: SWEEP_CHARS[dist],
|
|
76740
|
+
color: intensity > 0.3 ? PARTY_COLORS[colorIdx] : COLORS.borderStrong
|
|
76741
|
+
});
|
|
76742
|
+
} else {
|
|
76743
|
+
spans.push({ char: "\u2591", color: COLORS.bgSweepDim });
|
|
76744
|
+
}
|
|
76745
|
+
}
|
|
76746
|
+
return spans;
|
|
76747
|
+
}
|
|
76748
|
+
const left = buildSide(false);
|
|
76749
|
+
const right = buildSide(true);
|
|
76750
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76751
|
+
children: [
|
|
76752
|
+
left.map((s2, i2) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76753
|
+
fg: s2.color,
|
|
76754
|
+
children: s2.char
|
|
76755
|
+
}, "l" + i2, false, undefined, this)),
|
|
76756
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76757
|
+
fg: COLORS.textPrimary,
|
|
76758
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
76759
|
+
children: [
|
|
76760
|
+
" ",
|
|
76761
|
+
title,
|
|
76762
|
+
" "
|
|
76763
|
+
]
|
|
76764
|
+
}, undefined, true, undefined, this)
|
|
76765
|
+
}, undefined, false, undefined, this),
|
|
76766
|
+
right.map((s2, i2) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
76767
|
+
fg: s2.color,
|
|
76768
|
+
children: s2.char
|
|
76769
|
+
}, "r" + i2, false, undefined, this))
|
|
76770
|
+
]
|
|
76771
|
+
}, undefined, true, undefined, this);
|
|
76772
|
+
}
|
|
76773
|
+
function useDiscoColor() {
|
|
76774
|
+
const [idx, setIdx] = import_react19.useState(0);
|
|
76775
|
+
import_react19.useEffect(() => {
|
|
76776
|
+
const interval = setInterval(() => setIdx((i2) => (i2 + 1) % PARTY_COLORS.length), 800);
|
|
76777
|
+
return () => clearInterval(interval);
|
|
76778
|
+
}, []);
|
|
76779
|
+
return PARTY_COLORS[idx];
|
|
76780
|
+
}
|
|
76781
|
+
function ConfigWizard({ isFirstRun, onComplete, onCancel, existingConfig }) {
|
|
76782
|
+
const [step, setStep] = import_react19.useState("detect");
|
|
76783
|
+
const [detection, setDetection] = import_react19.useState([]);
|
|
76784
|
+
const [selectedIds, setSelectedIds] = import_react19.useState([]);
|
|
76785
|
+
const [, setAgentConfigs] = import_react19.useState([]);
|
|
76786
|
+
const [activeTab, setActiveTab] = import_react19.useState(0);
|
|
76787
|
+
const [focusedField, setFocusedField] = import_react19.useState(0);
|
|
76788
|
+
const [error, setError] = import_react19.useState("");
|
|
76789
|
+
const [, forceRender] = import_react19.useState(0);
|
|
76790
|
+
const inputRefs = import_react19.useRef([]);
|
|
76791
|
+
const humanRef = import_react19.useRef({
|
|
76792
|
+
name: existingConfig?.humanName || userInfo3().username || "USER",
|
|
76793
|
+
tag: existingConfig?.humanTag || toTag(existingConfig?.humanName || userInfo3().username || "USER")
|
|
76794
|
+
});
|
|
76795
|
+
const cursorRef = import_react19.useRef(0);
|
|
76796
|
+
const spinner = useSpinner();
|
|
76797
|
+
import_react19.useEffect(() => {
|
|
76798
|
+
detectProviders().then((results) => {
|
|
76799
|
+
setDetection(results);
|
|
76800
|
+
setStep("providers");
|
|
76801
|
+
});
|
|
76802
|
+
}, []);
|
|
76803
|
+
const existingByProvider = new Map((existingConfig?.agents || []).map((a2) => [a2.provider, a2]));
|
|
76804
|
+
const initialSelected = existingConfig ? PROVIDERS.map((p2, i2) => existingByProvider.has(p2.id) ? i2 : -1).filter((i2) => i2 >= 0) : undefined;
|
|
76805
|
+
const multiSelectItems = PROVIDERS.map((provider) => {
|
|
76806
|
+
const result = detection.find((d3) => d3.id === provider.id);
|
|
76807
|
+
const available = result?.available ?? false;
|
|
76808
|
+
return {
|
|
76809
|
+
label: provider.displayName,
|
|
76810
|
+
description: available ? provider.description : provider.unavailableHint,
|
|
76811
|
+
disabled: !available
|
|
76812
|
+
};
|
|
76813
|
+
});
|
|
76814
|
+
const handleProviderConfirm = import_react19.useCallback((selectedIndices) => {
|
|
76815
|
+
const ids = selectedIndices.map((i2) => PROVIDERS[i2].id);
|
|
76816
|
+
setSelectedIds(ids);
|
|
76817
|
+
const configs = ids.map((id) => {
|
|
76818
|
+
const def = PROVIDERS.find((p2) => p2.id === id);
|
|
76819
|
+
const existing = existingByProvider.get(id);
|
|
76820
|
+
return {
|
|
76821
|
+
id: def.id,
|
|
76822
|
+
name: existing?.name || def.displayName,
|
|
76823
|
+
tag: existing?.tag || def.defaultTag,
|
|
76824
|
+
model: existing?.model || def.defaultModel
|
|
76825
|
+
};
|
|
76826
|
+
});
|
|
76827
|
+
setAgentConfigs(configs);
|
|
76828
|
+
inputRefs.current = configs.map((c2) => ({ ...c2 }));
|
|
76829
|
+
setActiveTab(0);
|
|
76830
|
+
setFocusedField(0);
|
|
76831
|
+
cursorRef.current = configs[0]?.name.length || 0;
|
|
76832
|
+
setStep("configure");
|
|
76833
|
+
}, [existingByProvider]);
|
|
76834
|
+
const handleProviderCancel = import_react19.useCallback(() => {
|
|
76835
|
+
if (onCancel)
|
|
76836
|
+
onCancel();
|
|
76837
|
+
}, [onCancel]);
|
|
76838
|
+
const isYouTab = activeTab === 0;
|
|
76839
|
+
const agentTabIndex = activeTab - 1;
|
|
76840
|
+
const totalTabs = (inputRefs.current?.length || 0) + 1;
|
|
76841
|
+
const maxFieldIndex = isYouTab ? 1 : 2;
|
|
76842
|
+
const saveConfig = import_react19.useCallback(async () => {
|
|
76843
|
+
const configs = inputRefs.current;
|
|
76844
|
+
const human = humanRef.current;
|
|
76845
|
+
if (!human.name.trim()) {
|
|
76846
|
+
setError("Your name cannot be empty");
|
|
76847
|
+
return;
|
|
76848
|
+
}
|
|
76849
|
+
if (!human.tag.trim()) {
|
|
76850
|
+
setError("Your tag cannot be empty");
|
|
76851
|
+
return;
|
|
76852
|
+
}
|
|
76853
|
+
if (!TAG_PATTERN.test(human.tag.trim())) {
|
|
76854
|
+
setError("Your tag can only contain letters, numbers, hyphens, underscores");
|
|
76855
|
+
return;
|
|
76856
|
+
}
|
|
76857
|
+
for (const c2 of configs) {
|
|
76858
|
+
if (!c2.name.trim()) {
|
|
76859
|
+
setError(`Name cannot be empty for ${c2.id}`);
|
|
76860
|
+
return;
|
|
76861
|
+
}
|
|
76862
|
+
if (!c2.tag.trim()) {
|
|
76863
|
+
setError(`Tag cannot be empty for ${c2.id}`);
|
|
76864
|
+
return;
|
|
76865
|
+
}
|
|
76866
|
+
if (!TAG_PATTERN.test(c2.tag.trim())) {
|
|
76867
|
+
setError(`Tag for ${c2.name} can only contain letters, numbers, hyphens, underscores`);
|
|
76868
|
+
return;
|
|
76869
|
+
}
|
|
76870
|
+
if (!c2.model.trim()) {
|
|
76871
|
+
setError(`Model cannot be empty for ${c2.id}`);
|
|
76872
|
+
return;
|
|
76873
|
+
}
|
|
76874
|
+
}
|
|
76875
|
+
const names = new Set;
|
|
76876
|
+
for (const c2 of configs) {
|
|
76877
|
+
const lower = c2.name.trim().toLowerCase();
|
|
76878
|
+
if (names.has(lower)) {
|
|
76879
|
+
setError(`Duplicate agent name: ${c2.name}`);
|
|
76880
|
+
return;
|
|
76881
|
+
}
|
|
76882
|
+
names.add(lower);
|
|
76883
|
+
}
|
|
76884
|
+
const overrides = configs.map((c2) => ({
|
|
76885
|
+
id: c2.id,
|
|
76886
|
+
name: c2.name.trim(),
|
|
76887
|
+
tag: c2.tag.trim(),
|
|
76888
|
+
model: c2.model.trim()
|
|
76889
|
+
}));
|
|
76890
|
+
const mergedExisting = {
|
|
76891
|
+
...existingConfig || {},
|
|
76892
|
+
humanName: human.name.trim(),
|
|
76893
|
+
humanTag: human.tag.trim(),
|
|
76894
|
+
agents: existingConfig?.agents || []
|
|
76895
|
+
};
|
|
76896
|
+
try {
|
|
76897
|
+
await writeWizardConfig(selectedIds, overrides, mergedExisting);
|
|
76898
|
+
setStep("done");
|
|
76899
|
+
} catch (err) {
|
|
76900
|
+
setError(`Failed to save: ${err.message}`);
|
|
76901
|
+
}
|
|
76902
|
+
}, [selectedIds, existingConfig]);
|
|
76903
|
+
useKeyboard((key) => {
|
|
76904
|
+
if (step !== "configure") {
|
|
76905
|
+
if (step === "done") {
|
|
76906
|
+
if (key.name === "enter" || key.name === "return" || key.name === "space") {
|
|
76907
|
+
onComplete();
|
|
76908
|
+
}
|
|
76909
|
+
return;
|
|
76910
|
+
}
|
|
76911
|
+
return;
|
|
76912
|
+
}
|
|
76913
|
+
const configs = inputRefs.current;
|
|
76914
|
+
const human = humanRef.current;
|
|
76915
|
+
let fieldValue;
|
|
76916
|
+
if (isYouTab) {
|
|
76917
|
+
fieldValue = focusedField === 0 ? human.name : human.tag;
|
|
76918
|
+
} else {
|
|
76919
|
+
const current = configs[agentTabIndex];
|
|
76920
|
+
if (!current)
|
|
76921
|
+
return;
|
|
76922
|
+
fieldValue = [current.name, current.tag, current.model][focusedField];
|
|
76923
|
+
}
|
|
76924
|
+
const cursor = cursorRef.current;
|
|
76925
|
+
const updateField = (value, newCursor) => {
|
|
76926
|
+
if (isYouTab) {
|
|
76927
|
+
if (focusedField === 0)
|
|
76928
|
+
human.name = value;
|
|
76929
|
+
else
|
|
76930
|
+
human.tag = value;
|
|
76931
|
+
} else {
|
|
76932
|
+
const current = configs[agentTabIndex];
|
|
76933
|
+
if (focusedField === 0)
|
|
76934
|
+
current.name = value;
|
|
76935
|
+
else if (focusedField === 1)
|
|
76936
|
+
current.tag = value;
|
|
76937
|
+
else
|
|
76938
|
+
current.model = value;
|
|
76939
|
+
}
|
|
76940
|
+
cursorRef.current = newCursor;
|
|
76941
|
+
setError("");
|
|
76942
|
+
forceRender((n2) => n2 + 1);
|
|
76943
|
+
};
|
|
76944
|
+
if (key.sequence === "[" || key.sequence === "]") {
|
|
76945
|
+
const dir = key.sequence === "[" ? -1 : 1;
|
|
76946
|
+
const next = (activeTab + dir + totalTabs) % totalTabs;
|
|
76947
|
+
setActiveTab(next);
|
|
76948
|
+
const newMax = next === 0 ? 1 : 2;
|
|
76949
|
+
const newField = Math.min(focusedField, newMax);
|
|
76950
|
+
setFocusedField(newField);
|
|
76951
|
+
let newVal;
|
|
76952
|
+
if (next === 0) {
|
|
76953
|
+
newVal = newField === 0 ? human.name : human.tag;
|
|
76954
|
+
} else {
|
|
76955
|
+
newVal = getFieldValue(configs[next - 1], newField);
|
|
76956
|
+
}
|
|
76957
|
+
cursorRef.current = newVal.length;
|
|
76958
|
+
forceRender((n2) => n2 + 1);
|
|
76959
|
+
return;
|
|
76960
|
+
}
|
|
76961
|
+
if (key.name === "tab") {
|
|
76962
|
+
const fieldCount = maxFieldIndex + 1;
|
|
76963
|
+
const nextField = key.shift ? (focusedField - 1 + fieldCount) % fieldCount : (focusedField + 1) % fieldCount;
|
|
76964
|
+
setFocusedField(nextField);
|
|
76965
|
+
let newVal;
|
|
76966
|
+
if (isYouTab) {
|
|
76967
|
+
newVal = nextField === 0 ? human.name : human.tag;
|
|
76968
|
+
} else {
|
|
76969
|
+
newVal = getFieldValue(configs[agentTabIndex], nextField);
|
|
76970
|
+
}
|
|
76971
|
+
cursorRef.current = newVal.length;
|
|
76972
|
+
forceRender((n2) => n2 + 1);
|
|
76973
|
+
return;
|
|
76974
|
+
}
|
|
76975
|
+
if (key.name === "enter" || key.name === "return") {
|
|
76976
|
+
saveConfig();
|
|
76977
|
+
return;
|
|
76978
|
+
}
|
|
76979
|
+
if (key.name === "escape") {
|
|
76980
|
+
setStep("providers");
|
|
76981
|
+
setFocusedField(0);
|
|
76982
|
+
setActiveTab(0);
|
|
76983
|
+
return;
|
|
76984
|
+
}
|
|
76985
|
+
if (key.name === "backspace") {
|
|
76986
|
+
if (cursor > 0) {
|
|
76987
|
+
updateField(fieldValue.slice(0, cursor - 1) + fieldValue.slice(cursor), cursor - 1);
|
|
76988
|
+
}
|
|
76989
|
+
return;
|
|
76990
|
+
}
|
|
76991
|
+
if (key.name === "delete") {
|
|
76992
|
+
if (cursor < fieldValue.length) {
|
|
76993
|
+
updateField(fieldValue.slice(0, cursor) + fieldValue.slice(cursor + 1), cursor);
|
|
76994
|
+
}
|
|
76995
|
+
return;
|
|
76996
|
+
}
|
|
76997
|
+
if (key.name === "left") {
|
|
76998
|
+
cursorRef.current = Math.max(0, cursor - 1);
|
|
76999
|
+
forceRender((n2) => n2 + 1);
|
|
77000
|
+
return;
|
|
77001
|
+
}
|
|
77002
|
+
if (key.name === "right") {
|
|
77003
|
+
cursorRef.current = Math.min(fieldValue.length, cursor + 1);
|
|
77004
|
+
forceRender((n2) => n2 + 1);
|
|
77005
|
+
return;
|
|
77006
|
+
}
|
|
77007
|
+
if (key.name === "home" || key.ctrl && key.name === "a") {
|
|
77008
|
+
cursorRef.current = 0;
|
|
77009
|
+
forceRender((n2) => n2 + 1);
|
|
77010
|
+
return;
|
|
77011
|
+
}
|
|
77012
|
+
if (key.name === "end" || key.ctrl && key.name === "e") {
|
|
77013
|
+
cursorRef.current = fieldValue.length;
|
|
77014
|
+
forceRender((n2) => n2 + 1);
|
|
77015
|
+
return;
|
|
77016
|
+
}
|
|
77017
|
+
if (key.ctrl && key.name === "u") {
|
|
77018
|
+
updateField("", 0);
|
|
77019
|
+
return;
|
|
77020
|
+
}
|
|
77021
|
+
if (key.ctrl || key.name === "up" || key.name === "down" || key.name === "pageup" || key.name === "pagedown") {
|
|
77022
|
+
return;
|
|
77023
|
+
}
|
|
77024
|
+
if (key.name === "space" || key.sequence === " ") {
|
|
77025
|
+
if (focusedField !== 1) {
|
|
77026
|
+
updateField(fieldValue.slice(0, cursor) + " " + fieldValue.slice(cursor), cursor + 1);
|
|
77027
|
+
}
|
|
77028
|
+
return;
|
|
77029
|
+
}
|
|
77030
|
+
const ch = key.sequence;
|
|
77031
|
+
if (ch && ch.length > 0 && !ch.startsWith("\x1B")) {
|
|
77032
|
+
if (ch === "'" || ch === '"' || ch === "`")
|
|
77033
|
+
return;
|
|
77034
|
+
if (focusedField === 1 && !TAG_PATTERN.test(ch))
|
|
77035
|
+
return;
|
|
77036
|
+
updateField(fieldValue.slice(0, cursor) + ch + fieldValue.slice(cursor), cursor + ch.length);
|
|
77037
|
+
}
|
|
77038
|
+
});
|
|
77039
|
+
const title = isFirstRun ? "Welcome to llm-party" : "Configure Agents";
|
|
77040
|
+
const subtitle = isFirstRun ? "Bring your models. We'll bring the party." : "Changes will take effect on next session";
|
|
77041
|
+
const subtitleColor = isFirstRun ? COLORS.textDim : COLORS.warning;
|
|
77042
|
+
function Subtitle() {
|
|
77043
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77044
|
+
alignSelf: "center",
|
|
77045
|
+
fg: subtitleColor,
|
|
77046
|
+
children: subtitle
|
|
77047
|
+
}, undefined, false, undefined, this);
|
|
77048
|
+
}
|
|
77049
|
+
const discoColor = useDiscoColor();
|
|
77050
|
+
if (step === "detect") {
|
|
77051
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77052
|
+
flexDirection: "column",
|
|
77053
|
+
width: "100%",
|
|
77054
|
+
height: "100%",
|
|
77055
|
+
justifyContent: "center",
|
|
77056
|
+
alignItems: "center",
|
|
77057
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77058
|
+
border: true,
|
|
77059
|
+
borderStyle: "double",
|
|
77060
|
+
borderColor: discoColor,
|
|
77061
|
+
paddingX: 4,
|
|
77062
|
+
paddingY: 1,
|
|
77063
|
+
backgroundColor: COLORS.bgPanel,
|
|
77064
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77065
|
+
flexDirection: "column",
|
|
77066
|
+
alignItems: "center",
|
|
77067
|
+
children: [
|
|
77068
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SweepBar, {
|
|
77069
|
+
title: "llm-party"
|
|
77070
|
+
}, undefined, false, undefined, this),
|
|
77071
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77072
|
+
fg: COLORS.success,
|
|
77073
|
+
marginTop: 1,
|
|
77074
|
+
children: [
|
|
77075
|
+
spinner,
|
|
77076
|
+
" Scanning for installed CLIs..."
|
|
77077
|
+
]
|
|
77078
|
+
}, undefined, true, undefined, this)
|
|
77079
|
+
]
|
|
77080
|
+
}, undefined, true, undefined, this)
|
|
77081
|
+
}, undefined, false, undefined, this)
|
|
77082
|
+
}, undefined, false, undefined, this);
|
|
77083
|
+
}
|
|
77084
|
+
if (step === "providers") {
|
|
77085
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77086
|
+
flexDirection: "column",
|
|
77087
|
+
width: "100%",
|
|
77088
|
+
height: "100%",
|
|
77089
|
+
justifyContent: "center",
|
|
77090
|
+
alignItems: "center",
|
|
77091
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77092
|
+
border: true,
|
|
77093
|
+
borderStyle: "double",
|
|
77094
|
+
borderColor: discoColor,
|
|
77095
|
+
paddingX: 3,
|
|
77096
|
+
paddingY: 1,
|
|
77097
|
+
backgroundColor: COLORS.bgPanel,
|
|
77098
|
+
minWidth: 50,
|
|
77099
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77100
|
+
flexDirection: "column",
|
|
77101
|
+
children: [
|
|
77102
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77103
|
+
alignSelf: "center",
|
|
77104
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SweepBar, {
|
|
77105
|
+
title
|
|
77106
|
+
}, undefined, false, undefined, this)
|
|
77107
|
+
}, undefined, false, undefined, this),
|
|
77108
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Subtitle, {}, undefined, false, undefined, this),
|
|
77109
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77110
|
+
alignSelf: "center",
|
|
77111
|
+
fg: COLORS.textSubtle,
|
|
77112
|
+
marginTop: 1,
|
|
77113
|
+
children: "\u2550".repeat(44)
|
|
77114
|
+
}, undefined, false, undefined, this),
|
|
77115
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77116
|
+
marginTop: 1,
|
|
77117
|
+
children: [
|
|
77118
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77119
|
+
fg: COLORS.textSecondary,
|
|
77120
|
+
children: "Select your agents "
|
|
77121
|
+
}, undefined, false, undefined, this),
|
|
77122
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77123
|
+
fg: COLORS.success,
|
|
77124
|
+
children: "Space"
|
|
77125
|
+
}, undefined, false, undefined, this),
|
|
77126
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77127
|
+
fg: COLORS.textFaint,
|
|
77128
|
+
children: " toggle "
|
|
77129
|
+
}, undefined, false, undefined, this),
|
|
77130
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77131
|
+
fg: COLORS.success,
|
|
77132
|
+
children: "Enter"
|
|
77133
|
+
}, undefined, false, undefined, this),
|
|
77134
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77135
|
+
fg: COLORS.textFaint,
|
|
77136
|
+
children: " confirm"
|
|
77137
|
+
}, undefined, false, undefined, this),
|
|
77138
|
+
!isFirstRun && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
77139
|
+
children: [
|
|
77140
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77141
|
+
fg: COLORS.textFaint,
|
|
77142
|
+
children: " "
|
|
77143
|
+
}, undefined, false, undefined, this),
|
|
77144
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77145
|
+
fg: COLORS.error,
|
|
77146
|
+
children: "Esc"
|
|
77147
|
+
}, undefined, false, undefined, this),
|
|
77148
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77149
|
+
fg: COLORS.textFaint,
|
|
77150
|
+
children: " cancel"
|
|
77151
|
+
}, undefined, false, undefined, this)
|
|
77152
|
+
]
|
|
77153
|
+
}, undefined, true, undefined, this)
|
|
77154
|
+
]
|
|
77155
|
+
}, undefined, true, undefined, this),
|
|
77156
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77157
|
+
marginTop: 1,
|
|
77158
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(MultiSelect, {
|
|
77159
|
+
items: multiSelectItems,
|
|
77160
|
+
onConfirm: handleProviderConfirm,
|
|
77161
|
+
onCancel: isFirstRun ? undefined : handleProviderCancel,
|
|
77162
|
+
initialSelected
|
|
77163
|
+
}, undefined, false, undefined, this)
|
|
77164
|
+
}, undefined, false, undefined, this)
|
|
77165
|
+
]
|
|
77166
|
+
}, undefined, true, undefined, this)
|
|
77167
|
+
}, undefined, false, undefined, this)
|
|
77168
|
+
}, undefined, false, undefined, this);
|
|
77169
|
+
}
|
|
77170
|
+
if (step === "configure") {
|
|
77171
|
+
const configs = inputRefs.current;
|
|
77172
|
+
const human = humanRef.current;
|
|
77173
|
+
const tabLabels = ["You", ...selectedIds.map((id) => {
|
|
77174
|
+
const def = PROVIDERS.find((p2) => p2.id === id);
|
|
77175
|
+
return def?.displayName || id;
|
|
77176
|
+
})];
|
|
77177
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77178
|
+
flexDirection: "column",
|
|
77179
|
+
width: "100%",
|
|
77180
|
+
height: "100%",
|
|
77181
|
+
justifyContent: "center",
|
|
77182
|
+
alignItems: "center",
|
|
77183
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77184
|
+
border: true,
|
|
77185
|
+
borderStyle: "double",
|
|
77186
|
+
borderColor: discoColor,
|
|
77187
|
+
paddingX: 3,
|
|
77188
|
+
paddingY: 1,
|
|
77189
|
+
backgroundColor: COLORS.bgPanel,
|
|
77190
|
+
minWidth: 54,
|
|
77191
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77192
|
+
flexDirection: "column",
|
|
77193
|
+
children: [
|
|
77194
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77195
|
+
alignSelf: "center",
|
|
77196
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SweepBar, {
|
|
77197
|
+
title
|
|
77198
|
+
}, undefined, false, undefined, this)
|
|
77199
|
+
}, undefined, false, undefined, this),
|
|
77200
|
+
!isFirstRun && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(Subtitle, {}, undefined, false, undefined, this),
|
|
77201
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77202
|
+
flexDirection: "row",
|
|
77203
|
+
marginTop: 1,
|
|
77204
|
+
alignSelf: "center",
|
|
77205
|
+
children: tabLabels.map((label, i2) => {
|
|
77206
|
+
const isActive = i2 === activeTab;
|
|
77207
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77208
|
+
fg: isActive ? COLORS.success : COLORS.textSubtle,
|
|
77209
|
+
bg: isActive ? COLORS.bgActiveTab : undefined,
|
|
77210
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
77211
|
+
children: [
|
|
77212
|
+
" ",
|
|
77213
|
+
label,
|
|
77214
|
+
" "
|
|
77215
|
+
]
|
|
77216
|
+
}, undefined, true, undefined, this)
|
|
77217
|
+
}, label + i2, false, undefined, this);
|
|
77218
|
+
})
|
|
77219
|
+
}, undefined, false, undefined, this),
|
|
77220
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77221
|
+
alignSelf: "center",
|
|
77222
|
+
fg: COLORS.borderStrong,
|
|
77223
|
+
children: "\u2501".repeat(48)
|
|
77224
|
+
}, undefined, false, undefined, this),
|
|
77225
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77226
|
+
border: true,
|
|
77227
|
+
borderStyle: "rounded",
|
|
77228
|
+
borderColor: isYouTab ? COLORS.agent : COLORS.success,
|
|
77229
|
+
paddingX: 2,
|
|
77230
|
+
paddingY: 1,
|
|
77231
|
+
marginTop: 1,
|
|
77232
|
+
backgroundColor: COLORS.bgContent,
|
|
77233
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77234
|
+
flexDirection: "column",
|
|
77235
|
+
children: isYouTab ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
77236
|
+
children: [
|
|
77237
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77238
|
+
fg: COLORS.agent,
|
|
77239
|
+
marginBottom: 1,
|
|
77240
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
77241
|
+
children: "Your Identity"
|
|
77242
|
+
}, undefined, false, undefined, this)
|
|
77243
|
+
}, undefined, false, undefined, this),
|
|
77244
|
+
renderField("Name", human.name, focusedField === 0),
|
|
77245
|
+
renderField("Tag ", human.tag, focusedField === 1)
|
|
77246
|
+
]
|
|
77247
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(import_jsx_dev_runtime2.Fragment, {
|
|
77248
|
+
children: [
|
|
77249
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77250
|
+
fg: COLORS.success,
|
|
77251
|
+
marginBottom: 1,
|
|
77252
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
77253
|
+
children: [
|
|
77254
|
+
tabLabels[activeTab],
|
|
77255
|
+
" Configuration"
|
|
77256
|
+
]
|
|
77257
|
+
}, undefined, true, undefined, this)
|
|
77258
|
+
}, undefined, false, undefined, this),
|
|
77259
|
+
renderField("Name ", configs[agentTabIndex].name, focusedField === 0),
|
|
77260
|
+
renderField("Tag ", configs[agentTabIndex].tag, focusedField === 1),
|
|
77261
|
+
renderField("Model", configs[agentTabIndex].model, focusedField === 2)
|
|
77262
|
+
]
|
|
77263
|
+
}, undefined, true, undefined, this)
|
|
77264
|
+
}, undefined, false, undefined, this)
|
|
77265
|
+
}, undefined, false, undefined, this),
|
|
77266
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77267
|
+
flexDirection: "row",
|
|
77268
|
+
marginTop: 1,
|
|
77269
|
+
justifyContent: "space-between",
|
|
77270
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77271
|
+
children: [
|
|
77272
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77273
|
+
fg: COLORS.textFaint,
|
|
77274
|
+
children: "\u25C2 "
|
|
77275
|
+
}, undefined, false, undefined, this),
|
|
77276
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77277
|
+
fg: COLORS.success,
|
|
77278
|
+
children: "["
|
|
77279
|
+
}, undefined, false, undefined, this),
|
|
77280
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77281
|
+
fg: COLORS.textFaint,
|
|
77282
|
+
children: " prev "
|
|
77283
|
+
}, undefined, false, undefined, this),
|
|
77284
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77285
|
+
fg: COLORS.success,
|
|
77286
|
+
children: "]"
|
|
77287
|
+
}, undefined, false, undefined, this),
|
|
77288
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77289
|
+
fg: COLORS.textFaint,
|
|
77290
|
+
children: " next "
|
|
77291
|
+
}, undefined, false, undefined, this),
|
|
77292
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77293
|
+
fg: COLORS.textFaint,
|
|
77294
|
+
children: "\u25B8 "
|
|
77295
|
+
}, undefined, false, undefined, this),
|
|
77296
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77297
|
+
fg: COLORS.success,
|
|
77298
|
+
children: "Tab"
|
|
77299
|
+
}, undefined, false, undefined, this),
|
|
77300
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77301
|
+
fg: COLORS.textFaint,
|
|
77302
|
+
children: " fields "
|
|
77303
|
+
}, undefined, false, undefined, this),
|
|
77304
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77305
|
+
fg: COLORS.success,
|
|
77306
|
+
children: "Enter"
|
|
77307
|
+
}, undefined, false, undefined, this),
|
|
77308
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77309
|
+
fg: COLORS.textFaint,
|
|
77310
|
+
children: " save & close"
|
|
77311
|
+
}, undefined, false, undefined, this),
|
|
77312
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77313
|
+
fg: COLORS.textFaint,
|
|
77314
|
+
children: " "
|
|
77315
|
+
}, undefined, false, undefined, this),
|
|
77316
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77317
|
+
fg: COLORS.warning,
|
|
77318
|
+
children: "Esc"
|
|
77319
|
+
}, undefined, false, undefined, this),
|
|
77320
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77321
|
+
fg: COLORS.textFaint,
|
|
77322
|
+
children: " back"
|
|
77323
|
+
}, undefined, false, undefined, this)
|
|
77324
|
+
]
|
|
77325
|
+
}, undefined, true, undefined, this)
|
|
77326
|
+
}, undefined, false, undefined, this),
|
|
77327
|
+
error && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77328
|
+
border: true,
|
|
77329
|
+
borderStyle: "rounded",
|
|
77330
|
+
borderColor: COLORS.error,
|
|
77331
|
+
paddingX: 1,
|
|
77332
|
+
marginTop: 1,
|
|
77333
|
+
backgroundColor: COLORS.bgError,
|
|
77334
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77335
|
+
fg: COLORS.error,
|
|
77336
|
+
children: error
|
|
77337
|
+
}, undefined, false, undefined, this)
|
|
77338
|
+
}, undefined, false, undefined, this)
|
|
77339
|
+
]
|
|
77340
|
+
}, undefined, true, undefined, this)
|
|
77341
|
+
}, undefined, false, undefined, this)
|
|
77342
|
+
}, undefined, false, undefined, this);
|
|
77343
|
+
}
|
|
77344
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77345
|
+
flexDirection: "column",
|
|
77346
|
+
width: "100%",
|
|
77347
|
+
height: "100%",
|
|
77348
|
+
justifyContent: "center",
|
|
77349
|
+
alignItems: "center",
|
|
77350
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77351
|
+
border: true,
|
|
77352
|
+
borderStyle: "double",
|
|
77353
|
+
borderColor: discoColor,
|
|
77354
|
+
paddingX: 4,
|
|
77355
|
+
paddingY: 2,
|
|
77356
|
+
backgroundColor: COLORS.bgPanel,
|
|
77357
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77358
|
+
flexDirection: "column",
|
|
77359
|
+
alignItems: "center",
|
|
77360
|
+
children: [
|
|
77361
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(SweepBar, {
|
|
77362
|
+
title: "Config Saved"
|
|
77363
|
+
}, undefined, false, undefined, this),
|
|
77364
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77365
|
+
fg: COLORS.textSubtle,
|
|
77366
|
+
marginTop: 1,
|
|
77367
|
+
children: "\u2500".repeat(36)
|
|
77368
|
+
}, undefined, false, undefined, this),
|
|
77369
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77370
|
+
fg: COLORS.textMuted,
|
|
77371
|
+
marginTop: 1,
|
|
77372
|
+
children: "Written to ~/.llm-party/config.json"
|
|
77373
|
+
}, undefined, false, undefined, this),
|
|
77374
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77375
|
+
fg: COLORS.textSubtle,
|
|
77376
|
+
marginTop: 1,
|
|
77377
|
+
children: "Edit this file anytime to add prompts,"
|
|
77378
|
+
}, undefined, false, undefined, this),
|
|
77379
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77380
|
+
fg: COLORS.textSubtle,
|
|
77381
|
+
children: "env vars, or tweak settings."
|
|
77382
|
+
}, undefined, false, undefined, this),
|
|
77383
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77384
|
+
fg: COLORS.textSubtle,
|
|
77385
|
+
marginTop: 1,
|
|
77386
|
+
children: "\u2500".repeat(36)
|
|
77387
|
+
}, undefined, false, undefined, this),
|
|
77388
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77389
|
+
fg: COLORS.primary,
|
|
77390
|
+
marginTop: 1,
|
|
77391
|
+
children: [
|
|
77392
|
+
"Press ",
|
|
77393
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77394
|
+
fg: COLORS.success,
|
|
77395
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
77396
|
+
children: "Enter"
|
|
77397
|
+
}, undefined, false, undefined, this)
|
|
77398
|
+
}, undefined, false, undefined, this),
|
|
77399
|
+
" to continue"
|
|
77400
|
+
]
|
|
77401
|
+
}, undefined, true, undefined, this)
|
|
77402
|
+
]
|
|
77403
|
+
}, undefined, true, undefined, this)
|
|
77404
|
+
}, undefined, false, undefined, this)
|
|
77405
|
+
}, undefined, false, undefined, this);
|
|
77406
|
+
function renderField(label, value, isFocused) {
|
|
77407
|
+
const cursor = cursorRef.current;
|
|
77408
|
+
const labelColor = isFocused ? COLORS.primary : COLORS.textDim;
|
|
77409
|
+
const indicator = isFocused ? "\u25B8" : " ";
|
|
77410
|
+
const indicatorColor = COLORS.primary;
|
|
77411
|
+
const valueColor = isFocused ? COLORS.textPrimary : COLORS.textSecondary;
|
|
77412
|
+
if (!isFocused) {
|
|
77413
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77414
|
+
children: [
|
|
77415
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77416
|
+
fg: COLORS.borderStrong,
|
|
77417
|
+
children: [
|
|
77418
|
+
indicator,
|
|
77419
|
+
" "
|
|
77420
|
+
]
|
|
77421
|
+
}, undefined, true, undefined, this),
|
|
77422
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77423
|
+
fg: labelColor,
|
|
77424
|
+
children: [
|
|
77425
|
+
label,
|
|
77426
|
+
": "
|
|
77427
|
+
]
|
|
77428
|
+
}, undefined, true, undefined, this),
|
|
77429
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77430
|
+
fg: valueColor,
|
|
77431
|
+
children: value
|
|
77432
|
+
}, undefined, false, undefined, this)
|
|
77433
|
+
]
|
|
77434
|
+
}, undefined, true, undefined, this);
|
|
77435
|
+
}
|
|
77436
|
+
const before = value.slice(0, cursor);
|
|
77437
|
+
const cursorChar = cursor < value.length ? value[cursor] : " ";
|
|
77438
|
+
const after = cursor < value.length ? value.slice(cursor + 1) : "";
|
|
77439
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77440
|
+
children: [
|
|
77441
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77442
|
+
fg: indicatorColor,
|
|
77443
|
+
children: [
|
|
77444
|
+
indicator,
|
|
77445
|
+
" "
|
|
77446
|
+
]
|
|
77447
|
+
}, undefined, true, undefined, this),
|
|
77448
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77449
|
+
fg: labelColor,
|
|
77450
|
+
children: [
|
|
77451
|
+
label,
|
|
77452
|
+
": "
|
|
77453
|
+
]
|
|
77454
|
+
}, undefined, true, undefined, this),
|
|
77455
|
+
before,
|
|
77456
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77457
|
+
bg: COLORS.textPrimary,
|
|
77458
|
+
fg: "#000000",
|
|
77459
|
+
children: cursorChar
|
|
77460
|
+
}, undefined, false, undefined, this),
|
|
77461
|
+
after
|
|
77462
|
+
]
|
|
77463
|
+
}, undefined, true, undefined, this);
|
|
77464
|
+
}
|
|
77465
|
+
}
|
|
77466
|
+
function getFieldValue(config, field) {
|
|
77467
|
+
if (field === 0)
|
|
77468
|
+
return config.name;
|
|
77469
|
+
if (field === 1)
|
|
77470
|
+
return config.tag;
|
|
77471
|
+
return config.model;
|
|
77472
|
+
}
|
|
77473
|
+
|
|
77474
|
+
// src/ui/AgentsPanel.tsx
|
|
77475
|
+
function AgentsPanel({ agents, onClose, onConfig }) {
|
|
77476
|
+
useKeyboard((key) => {
|
|
77477
|
+
if (key.name === "escape") {
|
|
77478
|
+
onClose();
|
|
77479
|
+
return;
|
|
77480
|
+
}
|
|
77481
|
+
});
|
|
77482
|
+
const nameW = Math.max(4, ...agents.map((a2) => a2.name.length)) + 2;
|
|
77483
|
+
const tagW = Math.max(3, ...agents.map((a2) => a2.tag.length + 1)) + 2;
|
|
77484
|
+
const provW = Math.max(8, ...agents.map((a2) => a2.provider.length)) + 2;
|
|
77485
|
+
const modelW = Math.max(5, ...agents.map((a2) => a2.model.length)) + 2;
|
|
77486
|
+
const totalW = nameW + tagW + provW + modelW;
|
|
77487
|
+
const pad = (str, width) => str + " ".repeat(Math.max(0, width - str.length));
|
|
77488
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77489
|
+
position: "absolute",
|
|
77490
|
+
width: "100%",
|
|
77491
|
+
height: "100%",
|
|
77492
|
+
justifyContent: "center",
|
|
77493
|
+
alignItems: "center",
|
|
77494
|
+
zIndex: 10,
|
|
77495
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77496
|
+
border: true,
|
|
77497
|
+
borderStyle: "rounded",
|
|
77498
|
+
borderColor: COLORS.primary,
|
|
77499
|
+
paddingX: 3,
|
|
77500
|
+
paddingY: 1,
|
|
77501
|
+
backgroundColor: COLORS.bgPanel,
|
|
77502
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
77503
|
+
flexDirection: "column",
|
|
77504
|
+
children: [
|
|
77505
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77506
|
+
alignSelf: "center",
|
|
77507
|
+
fg: COLORS.primary,
|
|
77508
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("strong", {
|
|
77509
|
+
children: "Active Agents"
|
|
77510
|
+
}, undefined, false, undefined, this)
|
|
77511
|
+
}, undefined, false, undefined, this),
|
|
77512
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77513
|
+
fg: COLORS.textSubtle,
|
|
77514
|
+
marginTop: 1,
|
|
77515
|
+
children: [
|
|
77516
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77517
|
+
fg: COLORS.textMuted,
|
|
77518
|
+
children: pad("Name", nameW)
|
|
77519
|
+
}, undefined, false, undefined, this),
|
|
77520
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77521
|
+
fg: COLORS.textMuted,
|
|
77522
|
+
children: pad("Tag", tagW)
|
|
77523
|
+
}, undefined, false, undefined, this),
|
|
77524
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77525
|
+
fg: COLORS.textMuted,
|
|
77526
|
+
children: pad("Provider", provW)
|
|
77527
|
+
}, undefined, false, undefined, this),
|
|
77528
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77529
|
+
fg: COLORS.textMuted,
|
|
77530
|
+
children: pad("Model", modelW)
|
|
77531
|
+
}, undefined, false, undefined, this)
|
|
77532
|
+
]
|
|
77533
|
+
}, undefined, true, undefined, this),
|
|
77534
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77535
|
+
fg: COLORS.borderStrong,
|
|
77536
|
+
children: "\u2500".repeat(totalW)
|
|
77537
|
+
}, undefined, false, undefined, this),
|
|
77538
|
+
agents.map((a2) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77539
|
+
children: [
|
|
77540
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77541
|
+
fg: COLORS.textPrimary,
|
|
77542
|
+
children: pad(a2.name, nameW)
|
|
77543
|
+
}, undefined, false, undefined, this),
|
|
77544
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77545
|
+
fg: COLORS.success,
|
|
77546
|
+
children: pad("@" + a2.tag, tagW)
|
|
77547
|
+
}, undefined, false, undefined, this),
|
|
77548
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77549
|
+
fg: COLORS.textMuted,
|
|
77550
|
+
children: pad(a2.provider, provW)
|
|
77551
|
+
}, undefined, false, undefined, this),
|
|
77552
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77553
|
+
fg: COLORS.textDim,
|
|
77554
|
+
children: pad(a2.model, modelW)
|
|
77555
|
+
}, undefined, false, undefined, this)
|
|
77556
|
+
]
|
|
77557
|
+
}, a2.name, true, undefined, this)),
|
|
77558
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77559
|
+
fg: COLORS.borderStrong,
|
|
77560
|
+
marginTop: 1,
|
|
77561
|
+
children: "\u2500".repeat(totalW)
|
|
77562
|
+
}, undefined, false, undefined, this),
|
|
77563
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
77564
|
+
marginTop: 1,
|
|
77565
|
+
alignSelf: "center",
|
|
77566
|
+
children: [
|
|
77567
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77568
|
+
fg: COLORS.error,
|
|
77569
|
+
children: "Esc"
|
|
77570
|
+
}, undefined, false, undefined, this),
|
|
77571
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77572
|
+
fg: COLORS.textFaint,
|
|
77573
|
+
children: " close "
|
|
77574
|
+
}, undefined, false, undefined, this),
|
|
77575
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77576
|
+
fg: COLORS.success,
|
|
77577
|
+
children: "/config"
|
|
77578
|
+
}, undefined, false, undefined, this),
|
|
77579
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
|
|
77580
|
+
fg: COLORS.textFaint,
|
|
77581
|
+
children: " edit agents"
|
|
77582
|
+
}, undefined, false, undefined, this)
|
|
77583
|
+
]
|
|
77584
|
+
}, undefined, true, undefined, this)
|
|
77585
|
+
]
|
|
77586
|
+
}, undefined, true, undefined, this)
|
|
77587
|
+
}, undefined, false, undefined, this)
|
|
77588
|
+
}, undefined, false, undefined, this);
|
|
77589
|
+
}
|
|
77590
|
+
|
|
76431
77591
|
// src/ui/App.tsx
|
|
76432
77592
|
function copyToClipboard(text) {
|
|
76433
|
-
const proc =
|
|
77593
|
+
const proc = spawn5("pbcopy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
76434
77594
|
proc.stdin?.write(text);
|
|
76435
77595
|
proc.stdin?.end();
|
|
76436
77596
|
}
|
|
@@ -76445,23 +77605,31 @@ function copySelection(renderer) {
|
|
|
76445
77605
|
renderer.clearSelection?.();
|
|
76446
77606
|
return true;
|
|
76447
77607
|
}
|
|
76448
|
-
function App({ orchestrator, maxAutoHops, renderer }) {
|
|
77608
|
+
function App({ orchestrator, maxAutoHops, renderer, config }) {
|
|
76449
77609
|
const { messages, agentStates, stickyTarget, dispatching, dispatch, addSystemMessage, clearMessages } = useOrchestrator(orchestrator, maxAutoHops);
|
|
76450
77610
|
const humanName = orchestrator.getHumanName();
|
|
76451
77611
|
const agents = orchestrator.listAgents();
|
|
76452
|
-
const scrollRef =
|
|
76453
|
-
|
|
77612
|
+
const scrollRef = import_react22.useRef(null);
|
|
77613
|
+
const [screen, setScreen] = import_react22.useState("chat");
|
|
77614
|
+
const [showAgents, setShowAgents] = import_react22.useState(false);
|
|
77615
|
+
import_react22.useEffect(() => {
|
|
76454
77616
|
const sb = scrollRef.current;
|
|
76455
77617
|
if (sb && !sb.isDestroyed) {
|
|
76456
77618
|
sb.scrollTo(sb.scrollHeight);
|
|
76457
77619
|
}
|
|
76458
77620
|
}, [messages]);
|
|
76459
|
-
const gracefulExit =
|
|
77621
|
+
const gracefulExit = import_react22.useCallback(() => {
|
|
76460
77622
|
renderer.destroy();
|
|
76461
77623
|
const adapters = orchestrator.getAdapters();
|
|
76462
77624
|
Promise.allSettled(adapters.map((a2) => a2.destroy()));
|
|
76463
77625
|
}, [orchestrator, renderer]);
|
|
76464
77626
|
useKeyboard((key) => {
|
|
77627
|
+
if (key.ctrl && key.name === "p") {
|
|
77628
|
+
setShowAgents((v2) => !v2);
|
|
77629
|
+
return;
|
|
77630
|
+
}
|
|
77631
|
+
if (showAgents)
|
|
77632
|
+
return;
|
|
76465
77633
|
if (key.ctrl && key.name === "c") {
|
|
76466
77634
|
if (!copySelection(renderer)) {
|
|
76467
77635
|
gracefulExit();
|
|
@@ -76485,14 +77653,13 @@ function App({ orchestrator, maxAutoHops, renderer }) {
|
|
|
76485
77653
|
return;
|
|
76486
77654
|
}
|
|
76487
77655
|
});
|
|
76488
|
-
const handleSubmit =
|
|
77656
|
+
const handleSubmit = import_react22.useCallback(async (line) => {
|
|
76489
77657
|
if (line === "/exit") {
|
|
76490
77658
|
gracefulExit();
|
|
76491
77659
|
return;
|
|
76492
77660
|
}
|
|
76493
77661
|
if (line === "/agents") {
|
|
76494
|
-
|
|
76495
|
-
`));
|
|
77662
|
+
setShowAgents(true);
|
|
76496
77663
|
return;
|
|
76497
77664
|
}
|
|
76498
77665
|
if (line === "/session") {
|
|
@@ -76514,18 +77681,12 @@ Transcript: ${orchestrator.getTranscriptPath()}`);
|
|
|
76514
77681
|
clearMessages();
|
|
76515
77682
|
return;
|
|
76516
77683
|
}
|
|
77684
|
+
if (line === "/config") {
|
|
77685
|
+
setScreen("config");
|
|
77686
|
+
return;
|
|
77687
|
+
}
|
|
76517
77688
|
if (line === "/changes") {
|
|
76518
|
-
const
|
|
76519
|
-
const files = await new Promise((resolve4) => {
|
|
76520
|
-
execFile2("git", ["status", "--porcelain"], { cwd: process.cwd() }, (err, stdout) => {
|
|
76521
|
-
if (err) {
|
|
76522
|
-
resolve4([]);
|
|
76523
|
-
return;
|
|
76524
|
-
}
|
|
76525
|
-
resolve4(stdout.split(`
|
|
76526
|
-
`).filter((l) => l.length >= 4).map((l) => l.slice(3)));
|
|
76527
|
-
});
|
|
76528
|
-
});
|
|
77689
|
+
const files = await getChangedFiles();
|
|
76529
77690
|
addSystemMessage(files.length > 0 ? `Modified files:
|
|
76530
77691
|
${files.map((f) => ` ${f}`).join(`
|
|
76531
77692
|
`)}` : "No modified files.");
|
|
@@ -76549,6 +77710,17 @@ ${lines.join(`
|
|
|
76549
77710
|
await dispatch(line);
|
|
76550
77711
|
}, [orchestrator, dispatch, addSystemMessage, clearMessages, gracefulExit]);
|
|
76551
77712
|
const tagsLine = agents.map((a2) => `@${a2.tag}`).join(", ");
|
|
77713
|
+
if (screen === "config") {
|
|
77714
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(ConfigWizard, {
|
|
77715
|
+
isFirstRun: false,
|
|
77716
|
+
existingConfig: config,
|
|
77717
|
+
onComplete: () => {
|
|
77718
|
+
addSystemMessage("Config saved. Restart llm-party to apply changes.");
|
|
77719
|
+
setScreen("chat");
|
|
77720
|
+
},
|
|
77721
|
+
onCancel: () => setScreen("chat")
|
|
77722
|
+
}, undefined, false, undefined, this);
|
|
77723
|
+
}
|
|
76552
77724
|
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
76553
77725
|
flexDirection: "column",
|
|
76554
77726
|
width: "100%",
|
|
@@ -76564,12 +77736,12 @@ ${lines.join(`
|
|
|
76564
77736
|
flexShrink: 1,
|
|
76565
77737
|
children: [
|
|
76566
77738
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
76567
|
-
fg:
|
|
77739
|
+
fg: COLORS.primary,
|
|
76568
77740
|
selectable: true,
|
|
76569
77741
|
children: [
|
|
76570
77742
|
"llm-party | ",
|
|
76571
77743
|
tagsLine,
|
|
76572
|
-
" | /agents /session /save /changes /clear /exit"
|
|
77744
|
+
" | /agents /config /session /save /changes /clear /exit"
|
|
76573
77745
|
]
|
|
76574
77746
|
}, undefined, true, undefined, this),
|
|
76575
77747
|
messages.map((msg) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(MessageBubble, {
|
|
@@ -76587,7 +77759,16 @@ ${lines.join(`
|
|
|
76587
77759
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(InputLine, {
|
|
76588
77760
|
humanName,
|
|
76589
77761
|
onSubmit: handleSubmit,
|
|
76590
|
-
disabled: dispatching
|
|
77762
|
+
disabled: dispatching || showAgents,
|
|
77763
|
+
disabledMessage: showAgents ? "" : undefined
|
|
77764
|
+
}, undefined, false, undefined, this),
|
|
77765
|
+
showAgents && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(AgentsPanel, {
|
|
77766
|
+
agents,
|
|
77767
|
+
onClose: () => setShowAgents(false),
|
|
77768
|
+
onConfig: () => {
|
|
77769
|
+
setShowAgents(false);
|
|
77770
|
+
setScreen("config");
|
|
77771
|
+
}
|
|
76591
77772
|
}, undefined, false, undefined, this)
|
|
76592
77773
|
]
|
|
76593
77774
|
}, undefined, true, undefined, this);
|
|
@@ -76595,8 +77776,30 @@ ${lines.join(`
|
|
|
76595
77776
|
|
|
76596
77777
|
// src/index.ts
|
|
76597
77778
|
async function main2() {
|
|
76598
|
-
const appRoot =
|
|
77779
|
+
const appRoot = path11.resolve(path11.dirname(fileURLToPath3(import.meta.url)), "..");
|
|
76599
77780
|
await initLlmPartyHome(appRoot);
|
|
77781
|
+
const renderer = await createCliRenderer({
|
|
77782
|
+
exitOnCtrlC: false,
|
|
77783
|
+
useMouse: true,
|
|
77784
|
+
useKittyKeyboard: {}
|
|
77785
|
+
});
|
|
77786
|
+
process.on("SIGINT", () => {
|
|
77787
|
+
renderer.destroy();
|
|
77788
|
+
});
|
|
77789
|
+
const root = createRoot(renderer);
|
|
77790
|
+
const hasConfig = await configExists();
|
|
77791
|
+
if (!hasConfig) {
|
|
77792
|
+
root.render(import_react24.default.createElement(ConfigWizard, {
|
|
77793
|
+
isFirstRun: true,
|
|
77794
|
+
onComplete: async () => {
|
|
77795
|
+
await bootApp(appRoot, renderer, root);
|
|
77796
|
+
}
|
|
77797
|
+
}));
|
|
77798
|
+
} else {
|
|
77799
|
+
await bootApp(appRoot, renderer, root);
|
|
77800
|
+
}
|
|
77801
|
+
}
|
|
77802
|
+
async function bootApp(appRoot, renderer, root) {
|
|
76600
77803
|
const configPath = await resolveConfigPath(appRoot);
|
|
76601
77804
|
const config = await loadConfig2(configPath);
|
|
76602
77805
|
const humanName = config.humanName?.trim() || "USER";
|
|
@@ -76610,7 +77813,7 @@ async function main2() {
|
|
|
76610
77813
|
|
|
76611
77814
|
` + artifactsPrompt;
|
|
76612
77815
|
const resolveFromAppRoot = (value) => {
|
|
76613
|
-
return
|
|
77816
|
+
return path11.isAbsolute(value) ? value : path11.resolve(appRoot, value);
|
|
76614
77817
|
};
|
|
76615
77818
|
const adapters = await Promise.all(config.agents.map(async (agent, _index, allAgents) => {
|
|
76616
77819
|
const promptParts = [mergedBase];
|
|
@@ -76654,18 +77857,7 @@ async function main2() {
|
|
|
76654
77857
|
const defaultTimeout = typeof config.timeout === "number" && config.timeout > 0 ? config.timeout * 1000 : 600000;
|
|
76655
77858
|
const agentTimeouts = Object.fromEntries(config.agents.filter((agent) => typeof agent.timeout === "number" && agent.timeout > 0).map((agent) => [agent.name, agent.timeout * 1000]));
|
|
76656
77859
|
const orchestrator = new Orchestrator(adapters, humanName, Object.fromEntries(config.agents.map((agent) => [agent.name, agent.tag?.trim() || toTag(agent.name)])), humanTag, defaultTimeout, agentTimeouts);
|
|
76657
|
-
|
|
76658
|
-
exitOnCtrlC: false,
|
|
76659
|
-
useMouse: true,
|
|
76660
|
-
useKittyKeyboard: {},
|
|
76661
|
-
onDestroy: () => {
|
|
76662
|
-
Promise.allSettled(adapters.map((a2) => a2.destroy()));
|
|
76663
|
-
}
|
|
76664
|
-
});
|
|
76665
|
-
process.on("SIGINT", () => {
|
|
76666
|
-
renderer.destroy();
|
|
76667
|
-
});
|
|
76668
|
-
createRoot(renderer).render(import_react19.default.createElement(App, { orchestrator, maxAutoHops, renderer }));
|
|
77860
|
+
root.render(import_react24.default.createElement(App, { orchestrator, maxAutoHops, renderer, config }));
|
|
76669
77861
|
}
|
|
76670
77862
|
function resolveMaxAutoHops(value) {
|
|
76671
77863
|
if (value === "unlimited") {
|