llm-party-cli 0.7.0 → 0.9.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 +54 -22
- package/dist/index.js +686 -382
- package/package.json +1 -1
- package/prompts/artifacts.md +61 -4
- package/prompts/base.md +69 -7
package/dist/index.js
CHANGED
|
@@ -37551,8 +37551,11 @@ var render = async (node, rendererOrConfig = {}) => {
|
|
|
37551
37551
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
37552
37552
|
|
|
37553
37553
|
// src/adapters/base.ts
|
|
37554
|
-
function formatTranscript(messages) {
|
|
37555
|
-
return messages.map((m2) =>
|
|
37554
|
+
function formatTranscript(messages, agentName, humanName) {
|
|
37555
|
+
return messages.map((m2) => {
|
|
37556
|
+
const role = m2.from === agentName ? "you" : m2.from === humanName ? "user" : "agent";
|
|
37557
|
+
return `${m2.from} (${role}):: ${m2.text}`;
|
|
37558
|
+
}).join(`
|
|
37556
37559
|
|
|
37557
37560
|
`);
|
|
37558
37561
|
}
|
|
@@ -37561,13 +37564,15 @@ function formatTranscript(messages) {
|
|
|
37561
37564
|
class ClaudeBaseAdapter {
|
|
37562
37565
|
name;
|
|
37563
37566
|
model;
|
|
37567
|
+
humanName;
|
|
37564
37568
|
systemPrompt = "";
|
|
37565
37569
|
sessionId = "";
|
|
37566
37570
|
runtimeEnv = {};
|
|
37567
37571
|
claudeExecutable;
|
|
37568
|
-
constructor(name, model) {
|
|
37572
|
+
constructor(name, model, humanName) {
|
|
37569
37573
|
this.name = name;
|
|
37570
37574
|
this.model = model;
|
|
37575
|
+
this.humanName = humanName;
|
|
37571
37576
|
}
|
|
37572
37577
|
async init(config) {
|
|
37573
37578
|
this.systemPrompt = config.resolvedPrompt ?? "";
|
|
@@ -37575,10 +37580,23 @@ class ClaudeBaseAdapter {
|
|
|
37575
37580
|
this.claudeExecutable = config.executablePath ?? process.env.CLAUDE_CODE_EXECUTABLE;
|
|
37576
37581
|
}
|
|
37577
37582
|
async buildEnv(config) {
|
|
37578
|
-
|
|
37583
|
+
const configEnv = config.env ?? {};
|
|
37584
|
+
const mapped = {};
|
|
37585
|
+
if (configEnv.AUTH_URL) {
|
|
37586
|
+
mapped.ANTHROPIC_BASE_URL = configEnv.AUTH_URL;
|
|
37587
|
+
}
|
|
37588
|
+
if (configEnv.AUTH_TOKEN) {
|
|
37589
|
+
mapped.ANTHROPIC_AUTH_TOKEN = configEnv.AUTH_TOKEN;
|
|
37590
|
+
}
|
|
37591
|
+
if (configEnv.AUTH_URL || configEnv.AUTH_TOKEN) {
|
|
37592
|
+
mapped.ANTHROPIC_DEFAULT_HAIKU_MODEL = this.model;
|
|
37593
|
+
mapped.ANTHROPIC_DEFAULT_SONNET_MODEL = this.model;
|
|
37594
|
+
mapped.ANTHROPIC_DEFAULT_OPUS_MODEL = this.model;
|
|
37595
|
+
}
|
|
37596
|
+
return { ...process.env, ...mapped, ...configEnv };
|
|
37579
37597
|
}
|
|
37580
37598
|
async send(messages, signal) {
|
|
37581
|
-
return await this.querySDK(formatTranscript(messages), signal);
|
|
37599
|
+
return await this.querySDK(formatTranscript(messages, this.name, this.humanName), signal);
|
|
37582
37600
|
}
|
|
37583
37601
|
async destroy() {
|
|
37584
37602
|
return;
|
|
@@ -38061,11 +38079,13 @@ class CodexAdapter {
|
|
|
38061
38079
|
name;
|
|
38062
38080
|
provider = "codex";
|
|
38063
38081
|
model;
|
|
38082
|
+
humanName;
|
|
38064
38083
|
codex;
|
|
38065
38084
|
thread;
|
|
38066
|
-
constructor(name, model) {
|
|
38085
|
+
constructor(name, model, humanName) {
|
|
38067
38086
|
this.name = name;
|
|
38068
38087
|
this.model = model;
|
|
38088
|
+
this.humanName = humanName;
|
|
38069
38089
|
}
|
|
38070
38090
|
async init(config) {
|
|
38071
38091
|
const cliPath = config.executablePath ?? process.env.CODEX_CLI_EXECUTABLE;
|
|
@@ -38090,7 +38110,7 @@ class CodexAdapter {
|
|
|
38090
38110
|
if (signal?.aborted) {
|
|
38091
38111
|
return "[Aborted] Codex was cancelled";
|
|
38092
38112
|
}
|
|
38093
|
-
const turn = await this.thread.run(formatTranscript(messages));
|
|
38113
|
+
const turn = await this.thread.run(formatTranscript(messages, this.name, this.humanName));
|
|
38094
38114
|
if (turn.finalResponse && turn.finalResponse.length > 0) {
|
|
38095
38115
|
return turn.finalResponse;
|
|
38096
38116
|
}
|
|
@@ -39276,14 +39296,16 @@ class CopilotAdapter {
|
|
|
39276
39296
|
name;
|
|
39277
39297
|
provider = "copilot";
|
|
39278
39298
|
model;
|
|
39299
|
+
humanName;
|
|
39279
39300
|
client;
|
|
39280
39301
|
session;
|
|
39281
39302
|
systemPrompt = "";
|
|
39282
39303
|
cliPath;
|
|
39283
39304
|
timeout = 600000;
|
|
39284
|
-
constructor(name, model) {
|
|
39305
|
+
constructor(name, model, humanName) {
|
|
39285
39306
|
this.name = name;
|
|
39286
39307
|
this.model = model;
|
|
39308
|
+
this.humanName = humanName;
|
|
39287
39309
|
}
|
|
39288
39310
|
async init(config) {
|
|
39289
39311
|
this.systemPrompt = config.resolvedPrompt ?? "";
|
|
@@ -39300,7 +39322,7 @@ class CopilotAdapter {
|
|
|
39300
39322
|
if (signal?.aborted) {
|
|
39301
39323
|
return "[Aborted] Copilot was cancelled";
|
|
39302
39324
|
}
|
|
39303
|
-
const transcript = formatTranscript(messages);
|
|
39325
|
+
const transcript = formatTranscript(messages, this.name, this.humanName);
|
|
39304
39326
|
try {
|
|
39305
39327
|
return await this.sendToSession(transcript);
|
|
39306
39328
|
} catch (err) {
|
|
@@ -39354,62 +39376,9 @@ class CopilotAdapter {
|
|
|
39354
39376
|
}
|
|
39355
39377
|
}
|
|
39356
39378
|
|
|
39357
|
-
// src/adapters/
|
|
39358
|
-
|
|
39359
|
-
|
|
39360
|
-
provider = "glm";
|
|
39361
|
-
async buildEnv(config) {
|
|
39362
|
-
const aliasEnv = await loadGlmAliasEnv();
|
|
39363
|
-
return { ...process.env, ...aliasEnv, ...config.env ?? {} };
|
|
39364
|
-
}
|
|
39365
|
-
}
|
|
39366
|
-
function detectShell() {
|
|
39367
|
-
if (process.env.SHELL) {
|
|
39368
|
-
return process.env.SHELL;
|
|
39369
|
-
}
|
|
39370
|
-
return "/bin/sh";
|
|
39371
|
-
}
|
|
39372
|
-
async function loadGlmAliasEnv() {
|
|
39373
|
-
const shell = detectShell();
|
|
39374
|
-
const isInteractive = shell.endsWith("zsh") || shell.endsWith("bash");
|
|
39375
|
-
const args = isInteractive ? ["-ic", "alias glm"] : ["-c", "alias glm"];
|
|
39376
|
-
return new Promise((resolve4) => {
|
|
39377
|
-
const child = spawn3(shell, args, {
|
|
39378
|
-
cwd: process.cwd(),
|
|
39379
|
-
env: process.env,
|
|
39380
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
39381
|
-
});
|
|
39382
|
-
let stdout = "";
|
|
39383
|
-
const timeout = setTimeout(() => {
|
|
39384
|
-
child.kill("SIGTERM");
|
|
39385
|
-
resolve4({});
|
|
39386
|
-
}, 5000);
|
|
39387
|
-
child.stdout.on("data", (chunk) => {
|
|
39388
|
-
stdout += String(chunk);
|
|
39389
|
-
});
|
|
39390
|
-
child.on("close", (code) => {
|
|
39391
|
-
clearTimeout(timeout);
|
|
39392
|
-
if (code !== 0) {
|
|
39393
|
-
resolve4({});
|
|
39394
|
-
return;
|
|
39395
|
-
}
|
|
39396
|
-
const env2 = {};
|
|
39397
|
-
const tokens = stdout.match(/[A-Z_]+="[^"]*"/g) ?? [];
|
|
39398
|
-
for (const token of tokens) {
|
|
39399
|
-
const eqIdx = token.indexOf("=");
|
|
39400
|
-
if (eqIdx === -1)
|
|
39401
|
-
continue;
|
|
39402
|
-
const key = token.slice(0, eqIdx);
|
|
39403
|
-
const raw = token.slice(eqIdx + 1);
|
|
39404
|
-
env2[key] = raw.replace(/^"|"$/g, "");
|
|
39405
|
-
}
|
|
39406
|
-
resolve4(env2);
|
|
39407
|
-
});
|
|
39408
|
-
child.on("error", () => {
|
|
39409
|
-
clearTimeout(timeout);
|
|
39410
|
-
resolve4({});
|
|
39411
|
-
});
|
|
39412
|
-
});
|
|
39379
|
+
// src/adapters/custom.ts
|
|
39380
|
+
class CustomAdapter extends ClaudeBaseAdapter {
|
|
39381
|
+
provider = "custom";
|
|
39413
39382
|
}
|
|
39414
39383
|
|
|
39415
39384
|
// src/config/loader.ts
|
|
@@ -39448,27 +39417,11 @@ var PROVIDERS = [
|
|
|
39448
39417
|
defaultTag: "copilot",
|
|
39449
39418
|
detectCommand: "copilot",
|
|
39450
39419
|
detectType: "binary"
|
|
39451
|
-
},
|
|
39452
|
-
{
|
|
39453
|
-
id: "glm",
|
|
39454
|
-
displayName: "GLM",
|
|
39455
|
-
description: "glm alias configured on Claude Code CLI",
|
|
39456
|
-
unavailableHint: "glm shell alias not configured",
|
|
39457
|
-
defaultModel: "glm-5",
|
|
39458
|
-
defaultTag: "glm",
|
|
39459
|
-
detectCommand: "glm",
|
|
39460
|
-
detectType: "alias",
|
|
39461
|
-
env: {
|
|
39462
|
-
ANTHROPIC_BASE_URL: "https://api.z.ai/api/anthropic",
|
|
39463
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
|
39464
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.5",
|
|
39465
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5"
|
|
39466
|
-
}
|
|
39467
39420
|
}
|
|
39468
39421
|
];
|
|
39469
39422
|
|
|
39470
39423
|
// src/config/loader.ts
|
|
39471
|
-
var VALID_PROVIDER_IDS = new Set(PROVIDERS.map((p) => p.id));
|
|
39424
|
+
var VALID_PROVIDER_IDS = new Set([...PROVIDERS.map((p) => p.id), "custom"]);
|
|
39472
39425
|
var LLM_PARTY_HOME = path8.join(homedir(), ".llm-party");
|
|
39473
39426
|
var MIND_MAP_INDEX = `# Living Memory Neural Network
|
|
39474
39427
|
|
|
@@ -39654,9 +39607,23 @@ async function configExists() {
|
|
|
39654
39607
|
return false;
|
|
39655
39608
|
}
|
|
39656
39609
|
}
|
|
39610
|
+
function migrateProviders(data) {
|
|
39611
|
+
if (!Array.isArray(data.agents))
|
|
39612
|
+
return;
|
|
39613
|
+
for (const agent of data.agents) {
|
|
39614
|
+
if (!agent || typeof agent !== "object")
|
|
39615
|
+
continue;
|
|
39616
|
+
if (typeof agent.provider === "string" && !VALID_PROVIDER_IDS.has(agent.provider)) {
|
|
39617
|
+
agent.provider = "custom";
|
|
39618
|
+
if (!agent.cli)
|
|
39619
|
+
agent.cli = "claude";
|
|
39620
|
+
}
|
|
39621
|
+
}
|
|
39622
|
+
}
|
|
39657
39623
|
async function loadConfig2(configPath) {
|
|
39658
39624
|
const raw = await readFile3(configPath, "utf8");
|
|
39659
39625
|
const parsed = JSON.parse(raw);
|
|
39626
|
+
migrateProviders(parsed);
|
|
39660
39627
|
validateConfig(parsed);
|
|
39661
39628
|
return normalizeConfig(parsed);
|
|
39662
39629
|
}
|
|
@@ -39861,14 +39828,7 @@ class Orchestrator {
|
|
|
39861
39828
|
return this.agentTimeouts.get(agentName) ?? this.defaultTimeout;
|
|
39862
39829
|
}
|
|
39863
39830
|
buildInputForAgent(agentName, unseen) {
|
|
39864
|
-
const
|
|
39865
|
-
const merged = [...recent, ...unseen];
|
|
39866
|
-
const dedupById = new Map;
|
|
39867
|
-
for (const msg of merged) {
|
|
39868
|
-
dedupById.set(msg.id, msg);
|
|
39869
|
-
}
|
|
39870
|
-
const ordered = Array.from(dedupById.values()).sort((a, b2) => a.id - b2.id);
|
|
39871
|
-
const filtered = ordered.filter((msg) => msg.from.toUpperCase() !== agentName.toUpperCase());
|
|
39831
|
+
const filtered = unseen.filter((msg) => msg.from.toUpperCase() !== agentName.toUpperCase());
|
|
39872
39832
|
if (this.reminderInterval <= 0 || filtered.length < this.reminderInterval) {
|
|
39873
39833
|
return filtered;
|
|
39874
39834
|
}
|
|
@@ -39899,7 +39859,7 @@ function createSessionId() {
|
|
|
39899
39859
|
}
|
|
39900
39860
|
|
|
39901
39861
|
// src/ui/App.tsx
|
|
39902
|
-
import { spawn as
|
|
39862
|
+
import { spawn as spawn4 } from "child_process";
|
|
39903
39863
|
|
|
39904
39864
|
// src/ui/useOrchestrator.ts
|
|
39905
39865
|
import { execFile } from "child_process";
|
|
@@ -40321,7 +40281,7 @@ function InputLine(props) {
|
|
|
40321
40281
|
useKeyboard((key) => {
|
|
40322
40282
|
if (props.disabled)
|
|
40323
40283
|
return;
|
|
40324
|
-
if (key.shift && (key.name === "enter" || key.name === "return")) {
|
|
40284
|
+
if ((key.shift || key.option || key.meta) && (key.name === "enter" || key.name === "return")) {
|
|
40325
40285
|
update(value.slice(0, cursor) + `
|
|
40326
40286
|
` + value.slice(cursor), cursor + 1);
|
|
40327
40287
|
return;
|
|
@@ -40536,15 +40496,15 @@ function InputLine(props) {
|
|
|
40536
40496
|
}
|
|
40537
40497
|
|
|
40538
40498
|
// src/ui/ConfigWizard.tsx
|
|
40539
|
-
import { userInfo as
|
|
40499
|
+
import { userInfo as userInfo2 } from "os";
|
|
40540
40500
|
|
|
40541
40501
|
// src/config/detector.ts
|
|
40542
|
-
import { spawn as
|
|
40502
|
+
import { spawn as spawn3 } from "child_process";
|
|
40543
40503
|
var DETECT_TIMEOUT = 5000;
|
|
40544
40504
|
function detectBinary(command) {
|
|
40545
40505
|
return new Promise((resolve4) => {
|
|
40546
40506
|
const timer = setTimeout(() => resolve4({ available: false }), DETECT_TIMEOUT);
|
|
40547
|
-
const proc =
|
|
40507
|
+
const proc = spawn3(command, ["--version"], {
|
|
40548
40508
|
stdio: ["ignore", "pipe", "ignore"],
|
|
40549
40509
|
shell: true,
|
|
40550
40510
|
timeout: DETECT_TIMEOUT,
|
|
@@ -40569,33 +40529,13 @@ function detectBinary(command) {
|
|
|
40569
40529
|
});
|
|
40570
40530
|
});
|
|
40571
40531
|
}
|
|
40572
|
-
function detectAlias(command) {
|
|
40573
|
-
return new Promise((resolve4) => {
|
|
40574
|
-
const shell = process.env.SHELL || "/bin/bash";
|
|
40575
|
-
const timer = setTimeout(() => resolve4({ available: false }), DETECT_TIMEOUT);
|
|
40576
|
-
const proc = spawn4(shell, ["-ic", `type ${command}`], {
|
|
40577
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
40578
|
-
timeout: DETECT_TIMEOUT,
|
|
40579
|
-
detached: true
|
|
40580
|
-
});
|
|
40581
|
-
proc.unref();
|
|
40582
|
-
proc.on("close", (code) => {
|
|
40583
|
-
clearTimeout(timer);
|
|
40584
|
-
resolve4({ available: code === 0 });
|
|
40585
|
-
});
|
|
40586
|
-
proc.on("error", () => {
|
|
40587
|
-
clearTimeout(timer);
|
|
40588
|
-
resolve4({ available: false });
|
|
40589
|
-
});
|
|
40590
|
-
});
|
|
40591
|
-
}
|
|
40592
40532
|
async function detectProviders() {
|
|
40593
40533
|
const results = await Promise.allSettled(PROVIDERS.map(async (provider) => {
|
|
40594
|
-
const result =
|
|
40534
|
+
const result = await detectBinary(provider.detectCommand);
|
|
40595
40535
|
return {
|
|
40596
40536
|
id: provider.id,
|
|
40597
40537
|
available: result.available,
|
|
40598
|
-
version:
|
|
40538
|
+
version: result.version
|
|
40599
40539
|
};
|
|
40600
40540
|
}));
|
|
40601
40541
|
return results.map((result, i) => {
|
|
@@ -40607,57 +40547,8 @@ async function detectProviders() {
|
|
|
40607
40547
|
|
|
40608
40548
|
// src/config/writer.ts
|
|
40609
40549
|
import { writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
|
|
40610
|
-
import { userInfo as userInfo2 } from "os";
|
|
40611
40550
|
import path10 from "path";
|
|
40612
|
-
async function
|
|
40613
|
-
const overrideMap = new Map((overrides || []).map((o) => [o.id, o]));
|
|
40614
|
-
const existingByProvider = new Map;
|
|
40615
|
-
if (existingConfig?.agents) {
|
|
40616
|
-
for (const agent of existingConfig.agents) {
|
|
40617
|
-
existingByProvider.set(agent.provider, agent);
|
|
40618
|
-
}
|
|
40619
|
-
}
|
|
40620
|
-
const agents = selectedIds.map((id) => {
|
|
40621
|
-
const def = PROVIDERS.find((p) => p.id === id);
|
|
40622
|
-
if (!def)
|
|
40623
|
-
throw new Error(`Unknown provider: ${id}`);
|
|
40624
|
-
const override = overrideMap.get(id);
|
|
40625
|
-
const existing = existingByProvider.get(id);
|
|
40626
|
-
const agent = {
|
|
40627
|
-
name: override?.name || def.displayName,
|
|
40628
|
-
tag: override?.tag || def.defaultTag,
|
|
40629
|
-
provider: def.id,
|
|
40630
|
-
model: override?.model || def.defaultModel
|
|
40631
|
-
};
|
|
40632
|
-
if (existing?.env) {
|
|
40633
|
-
agent.env = { ...existing.env };
|
|
40634
|
-
} else if (def.env) {
|
|
40635
|
-
agent.env = { ...def.env };
|
|
40636
|
-
}
|
|
40637
|
-
if (existing?.prompts)
|
|
40638
|
-
agent.prompts = existing.prompts;
|
|
40639
|
-
if (existing?.preloadSkills)
|
|
40640
|
-
agent.preloadSkills = existing.preloadSkills;
|
|
40641
|
-
if (existing?.executablePath)
|
|
40642
|
-
agent.executablePath = existing.executablePath;
|
|
40643
|
-
if (existing?.timeout)
|
|
40644
|
-
agent.timeout = existing.timeout;
|
|
40645
|
-
return agent;
|
|
40646
|
-
});
|
|
40647
|
-
const config = {
|
|
40648
|
-
humanName: existingConfig?.humanName || userInfo2().username || "USER",
|
|
40649
|
-
humanTag: existingConfig?.humanTag,
|
|
40650
|
-
maxAutoHops: existingConfig?.maxAutoHops ?? 15,
|
|
40651
|
-
timeout: existingConfig?.timeout,
|
|
40652
|
-
reminderInterval: existingConfig?.reminderInterval,
|
|
40653
|
-
agents
|
|
40654
|
-
};
|
|
40655
|
-
if (!config.humanTag)
|
|
40656
|
-
delete config.humanTag;
|
|
40657
|
-
if (config.timeout === undefined)
|
|
40658
|
-
delete config.timeout;
|
|
40659
|
-
if (config.reminderInterval === undefined)
|
|
40660
|
-
delete config.reminderInterval;
|
|
40551
|
+
async function writeConfig(config) {
|
|
40661
40552
|
await mkdir6(LLM_PARTY_HOME, { recursive: true });
|
|
40662
40553
|
const configPath = path10.join(LLM_PARTY_HOME, "config.json");
|
|
40663
40554
|
await writeFile6(configPath, JSON.stringify(config, null, 2) + `
|
|
@@ -40670,16 +40561,114 @@ function MultiSelect(props) {
|
|
|
40670
40561
|
const [focused, setFocused] = createSignal(props.items.findIndex((item) => !item.disabled));
|
|
40671
40562
|
const [selected, setSelected] = createSignal(new Set(props.initialSelected || []));
|
|
40672
40563
|
const [error, setError] = createSignal("");
|
|
40564
|
+
const [addingCustom, setAddingCustom] = createSignal(false);
|
|
40565
|
+
const [customName, setCustomName] = createSignal("");
|
|
40566
|
+
const [customCursor, setCustomCursor] = createSignal(0);
|
|
40567
|
+
const tuiRenderer = useRenderer();
|
|
40568
|
+
createEffect(() => {
|
|
40569
|
+
const handlePaste = (event) => {
|
|
40570
|
+
if (!addingCustom())
|
|
40571
|
+
return;
|
|
40572
|
+
const text = new TextDecoder().decode(event.bytes);
|
|
40573
|
+
if (!text)
|
|
40574
|
+
return;
|
|
40575
|
+
const cleaned = text.replace(/\n/g, "");
|
|
40576
|
+
if (!cleaned)
|
|
40577
|
+
return;
|
|
40578
|
+
const c = customCursor();
|
|
40579
|
+
const val = customName();
|
|
40580
|
+
setCustomName(val.slice(0, c) + cleaned + val.slice(c));
|
|
40581
|
+
setCustomCursor(c + cleaned.length);
|
|
40582
|
+
};
|
|
40583
|
+
tuiRenderer.keyInput.on("paste", handlePaste);
|
|
40584
|
+
onCleanup(() => {
|
|
40585
|
+
tuiRenderer.keyInput.off("paste", handlePaste);
|
|
40586
|
+
});
|
|
40587
|
+
});
|
|
40588
|
+
const totalRows = () => props.items.length + (props.addCustom ? 1 : 0);
|
|
40589
|
+
const isAddCustomRow = (idx) => props.addCustom && idx === props.items.length;
|
|
40673
40590
|
const findNextEnabled = (from, direction) => {
|
|
40591
|
+
const total = totalRows();
|
|
40674
40592
|
let idx = from;
|
|
40675
|
-
for (let i = 0;i <
|
|
40676
|
-
idx = (idx + direction +
|
|
40593
|
+
for (let i = 0;i < total; i++) {
|
|
40594
|
+
idx = (idx + direction + total) % total;
|
|
40595
|
+
if (isAddCustomRow(idx))
|
|
40596
|
+
return idx;
|
|
40677
40597
|
if (!props.items[idx].disabled)
|
|
40678
40598
|
return idx;
|
|
40679
40599
|
}
|
|
40680
40600
|
return from;
|
|
40681
40601
|
};
|
|
40682
40602
|
useKeyboard((key) => {
|
|
40603
|
+
if (addingCustom()) {
|
|
40604
|
+
if (key.name === "escape") {
|
|
40605
|
+
setAddingCustom(false);
|
|
40606
|
+
setCustomName("");
|
|
40607
|
+
setCustomCursor(0);
|
|
40608
|
+
return;
|
|
40609
|
+
}
|
|
40610
|
+
if (key.name === "enter" || key.name === "return") {
|
|
40611
|
+
const name = customName().trim();
|
|
40612
|
+
if (name.length > 0) {
|
|
40613
|
+
props.addCustom.onAdd(name);
|
|
40614
|
+
setAddingCustom(false);
|
|
40615
|
+
setCustomName("");
|
|
40616
|
+
setCustomCursor(0);
|
|
40617
|
+
}
|
|
40618
|
+
return;
|
|
40619
|
+
}
|
|
40620
|
+
if (key.name === "backspace") {
|
|
40621
|
+
const c = customCursor();
|
|
40622
|
+
if (c > 0) {
|
|
40623
|
+
const val = customName();
|
|
40624
|
+
setCustomName(val.slice(0, c - 1) + val.slice(c));
|
|
40625
|
+
setCustomCursor(c - 1);
|
|
40626
|
+
}
|
|
40627
|
+
return;
|
|
40628
|
+
}
|
|
40629
|
+
if (key.name === "delete") {
|
|
40630
|
+
const c = customCursor();
|
|
40631
|
+
const val = customName();
|
|
40632
|
+
if (c < val.length) {
|
|
40633
|
+
setCustomName(val.slice(0, c) + val.slice(c + 1));
|
|
40634
|
+
}
|
|
40635
|
+
return;
|
|
40636
|
+
}
|
|
40637
|
+
if (key.name === "left") {
|
|
40638
|
+
setCustomCursor((c) => Math.max(0, c - 1));
|
|
40639
|
+
return;
|
|
40640
|
+
}
|
|
40641
|
+
if (key.name === "right") {
|
|
40642
|
+
setCustomCursor((c) => Math.min(customName().length, c + 1));
|
|
40643
|
+
return;
|
|
40644
|
+
}
|
|
40645
|
+
if (key.name === "home" || key.ctrl && key.name === "a") {
|
|
40646
|
+
setCustomCursor(0);
|
|
40647
|
+
return;
|
|
40648
|
+
}
|
|
40649
|
+
if (key.name === "end" || key.ctrl && key.name === "e") {
|
|
40650
|
+
setCustomCursor(customName().length);
|
|
40651
|
+
return;
|
|
40652
|
+
}
|
|
40653
|
+
if (key.ctrl && key.name === "u") {
|
|
40654
|
+
setCustomName("");
|
|
40655
|
+
setCustomCursor(0);
|
|
40656
|
+
return;
|
|
40657
|
+
}
|
|
40658
|
+
if (key.ctrl || key.name === "up" || key.name === "down" || key.name === "pageup" || key.name === "pagedown" || key.name === "tab") {
|
|
40659
|
+
return;
|
|
40660
|
+
}
|
|
40661
|
+
const ch = key.sequence;
|
|
40662
|
+
if (ch && ch.length > 0 && !ch.startsWith("\x1B")) {
|
|
40663
|
+
if (ch === "'" || ch === '"' || ch === "`")
|
|
40664
|
+
return;
|
|
40665
|
+
const c = customCursor();
|
|
40666
|
+
const val = customName();
|
|
40667
|
+
setCustomName(val.slice(0, c) + ch + val.slice(c));
|
|
40668
|
+
setCustomCursor(c + ch.length);
|
|
40669
|
+
}
|
|
40670
|
+
return;
|
|
40671
|
+
}
|
|
40683
40672
|
if (key.name === "up" || key.name === "k") {
|
|
40684
40673
|
setFocused((f) => findNextEnabled(f, -1));
|
|
40685
40674
|
setError("");
|
|
@@ -40691,13 +40680,20 @@ function MultiSelect(props) {
|
|
|
40691
40680
|
return;
|
|
40692
40681
|
}
|
|
40693
40682
|
if (key.name === "space" || key.sequence === " ") {
|
|
40694
|
-
|
|
40683
|
+
const f = focused();
|
|
40684
|
+
if (isAddCustomRow(f)) {
|
|
40685
|
+
setAddingCustom(true);
|
|
40686
|
+
setCustomName("");
|
|
40687
|
+
setCustomCursor(0);
|
|
40688
|
+
return;
|
|
40689
|
+
}
|
|
40690
|
+
if (f >= 0 && !props.items[f].disabled) {
|
|
40695
40691
|
setSelected((prev) => {
|
|
40696
40692
|
const next = new Set(prev);
|
|
40697
|
-
if (next.has(
|
|
40698
|
-
next.delete(
|
|
40693
|
+
if (next.has(f)) {
|
|
40694
|
+
next.delete(f);
|
|
40699
40695
|
} else {
|
|
40700
|
-
next.add(
|
|
40696
|
+
next.add(f);
|
|
40701
40697
|
}
|
|
40702
40698
|
return next;
|
|
40703
40699
|
});
|
|
@@ -40706,6 +40702,13 @@ function MultiSelect(props) {
|
|
|
40706
40702
|
return;
|
|
40707
40703
|
}
|
|
40708
40704
|
if (key.name === "enter" || key.name === "return") {
|
|
40705
|
+
const f = focused();
|
|
40706
|
+
if (isAddCustomRow(f)) {
|
|
40707
|
+
setAddingCustom(true);
|
|
40708
|
+
setCustomName("");
|
|
40709
|
+
setCustomCursor(0);
|
|
40710
|
+
return;
|
|
40711
|
+
}
|
|
40709
40712
|
if (selected().size === 0) {
|
|
40710
40713
|
setError("Select at least one agent");
|
|
40711
40714
|
return;
|
|
@@ -40727,7 +40730,7 @@ function MultiSelect(props) {
|
|
|
40727
40730
|
},
|
|
40728
40731
|
children: (item, i) => {
|
|
40729
40732
|
const isSelected = () => selected().has(i());
|
|
40730
|
-
const isFocused = () => i() === focused();
|
|
40733
|
+
const isFocused = () => i() === focused() && !addingCustom();
|
|
40731
40734
|
const isDisabled = () => !!item.disabled;
|
|
40732
40735
|
const bullet = () => isSelected() ? "\u25CF" : "\u25CB";
|
|
40733
40736
|
const bulletColor = () => isDisabled() ? COLORS.textFaint : isSelected() ? COLORS.success : COLORS.textSecondary;
|
|
@@ -40735,29 +40738,29 @@ function MultiSelect(props) {
|
|
|
40735
40738
|
const descColor = () => isDisabled() ? COLORS.textFaint : COLORS.textMuted;
|
|
40736
40739
|
const bgColor = () => isFocused() && !isDisabled() ? COLORS.bgFocus : undefined;
|
|
40737
40740
|
return (() => {
|
|
40738
|
-
var _el$
|
|
40739
|
-
insertNode(_el$
|
|
40740
|
-
insertNode(_el$
|
|
40741
|
-
insertNode(_el$
|
|
40742
|
-
setProp(_el$
|
|
40743
|
-
insertNode(_el$
|
|
40744
|
-
insertNode(_el$
|
|
40745
|
-
insert(_el$
|
|
40746
|
-
insert(_el$
|
|
40747
|
-
insertNode(_el$
|
|
40748
|
-
insert(_el$
|
|
40741
|
+
var _el$0 = createElement("text"), _el$1 = createElement("span"), _el$10 = createTextNode(` `), _el$11 = createTextNode(` `), _el$12 = createElement("span"), _el$13 = createElement("span"), _el$14 = createTextNode(` `);
|
|
40742
|
+
insertNode(_el$0, _el$1);
|
|
40743
|
+
insertNode(_el$0, _el$12);
|
|
40744
|
+
insertNode(_el$0, _el$13);
|
|
40745
|
+
setProp(_el$0, "selectable", false);
|
|
40746
|
+
insertNode(_el$1, _el$10);
|
|
40747
|
+
insertNode(_el$1, _el$11);
|
|
40748
|
+
insert(_el$1, bullet, _el$11);
|
|
40749
|
+
insert(_el$12, () => item.label);
|
|
40750
|
+
insertNode(_el$13, _el$14);
|
|
40751
|
+
insert(_el$13, () => item.description, null);
|
|
40749
40752
|
effect((_p$) => {
|
|
40750
|
-
var _v$ = bgColor(), _v$
|
|
40753
|
+
var _v$4 = bgColor(), _v$5 = {
|
|
40751
40754
|
fg: bulletColor()
|
|
40752
|
-
}, _v$
|
|
40755
|
+
}, _v$6 = {
|
|
40753
40756
|
fg: labelColor()
|
|
40754
|
-
}, _v$
|
|
40757
|
+
}, _v$7 = {
|
|
40755
40758
|
fg: descColor()
|
|
40756
40759
|
};
|
|
40757
|
-
_v$ !== _p$.e && (_p$.e = setProp(_el$
|
|
40758
|
-
_v$
|
|
40759
|
-
_v$
|
|
40760
|
-
_v$
|
|
40760
|
+
_v$4 !== _p$.e && (_p$.e = setProp(_el$0, "bg", _v$4, _p$.e));
|
|
40761
|
+
_v$5 !== _p$.t && (_p$.t = setProp(_el$1, "style", _v$5, _p$.t));
|
|
40762
|
+
_v$6 !== _p$.a && (_p$.a = setProp(_el$12, "style", _v$6, _p$.a));
|
|
40763
|
+
_v$7 !== _p$.o && (_p$.o = setProp(_el$13, "style", _v$7, _p$.o));
|
|
40761
40764
|
return _p$;
|
|
40762
40765
|
}, {
|
|
40763
40766
|
e: undefined,
|
|
@@ -40765,21 +40768,96 @@ function MultiSelect(props) {
|
|
|
40765
40768
|
a: undefined,
|
|
40766
40769
|
o: undefined
|
|
40767
40770
|
});
|
|
40768
|
-
return _el$
|
|
40771
|
+
return _el$0;
|
|
40769
40772
|
})();
|
|
40770
40773
|
}
|
|
40771
40774
|
}), null);
|
|
40775
|
+
insert(_el$, createComponent2(Show, {
|
|
40776
|
+
get when() {
|
|
40777
|
+
return props.addCustom;
|
|
40778
|
+
},
|
|
40779
|
+
get children() {
|
|
40780
|
+
return createComponent2(Show, {
|
|
40781
|
+
get when() {
|
|
40782
|
+
return addingCustom();
|
|
40783
|
+
},
|
|
40784
|
+
get fallback() {
|
|
40785
|
+
return (() => {
|
|
40786
|
+
var _el$15 = createElement("text"), _el$16 = createElement("span"), _el$18 = createElement("span");
|
|
40787
|
+
insertNode(_el$15, _el$16);
|
|
40788
|
+
insertNode(_el$15, _el$18);
|
|
40789
|
+
setProp(_el$15, "selectable", false);
|
|
40790
|
+
insertNode(_el$16, createTextNode(` + `));
|
|
40791
|
+
insertNode(_el$18, createTextNode(`Add Custom...`));
|
|
40792
|
+
effect((_p$) => {
|
|
40793
|
+
var _v$8 = focused() === props.items.length && !addingCustom() ? COLORS.bgFocus : undefined, _v$9 = {
|
|
40794
|
+
fg: COLORS.primary
|
|
40795
|
+
}, _v$0 = {
|
|
40796
|
+
fg: COLORS.textSecondary
|
|
40797
|
+
};
|
|
40798
|
+
_v$8 !== _p$.e && (_p$.e = setProp(_el$15, "bg", _v$8, _p$.e));
|
|
40799
|
+
_v$9 !== _p$.t && (_p$.t = setProp(_el$16, "style", _v$9, _p$.t));
|
|
40800
|
+
_v$0 !== _p$.a && (_p$.a = setProp(_el$18, "style", _v$0, _p$.a));
|
|
40801
|
+
return _p$;
|
|
40802
|
+
}, {
|
|
40803
|
+
e: undefined,
|
|
40804
|
+
t: undefined,
|
|
40805
|
+
a: undefined
|
|
40806
|
+
});
|
|
40807
|
+
return _el$15;
|
|
40808
|
+
})();
|
|
40809
|
+
},
|
|
40810
|
+
get children() {
|
|
40811
|
+
var _el$2 = createElement("text"), _el$3 = createElement("span"), _el$5 = createElement("span"), _el$7 = createElement("span");
|
|
40812
|
+
insertNode(_el$2, _el$3);
|
|
40813
|
+
insertNode(_el$2, _el$5);
|
|
40814
|
+
insertNode(_el$2, _el$7);
|
|
40815
|
+
setProp(_el$2, "selectable", false);
|
|
40816
|
+
insertNode(_el$3, createTextNode(` + `));
|
|
40817
|
+
insertNode(_el$5, createTextNode(`Name: `));
|
|
40818
|
+
insert(_el$2, () => customName().slice(0, customCursor()), _el$7);
|
|
40819
|
+
insert(_el$7, (() => {
|
|
40820
|
+
var _c$ = memo2(() => customCursor() < customName().length);
|
|
40821
|
+
return () => _c$() ? customName()[customCursor()] : " ";
|
|
40822
|
+
})());
|
|
40823
|
+
insert(_el$2, (() => {
|
|
40824
|
+
var _c$2 = memo2(() => customCursor() < customName().length);
|
|
40825
|
+
return () => _c$2() ? customName().slice(customCursor() + 1) : "";
|
|
40826
|
+
})(), null);
|
|
40827
|
+
effect((_p$) => {
|
|
40828
|
+
var _v$ = {
|
|
40829
|
+
fg: COLORS.primary
|
|
40830
|
+
}, _v$2 = {
|
|
40831
|
+
fg: COLORS.textSecondary
|
|
40832
|
+
}, _v$3 = {
|
|
40833
|
+
bg: COLORS.textPrimary,
|
|
40834
|
+
fg: "#000000"
|
|
40835
|
+
};
|
|
40836
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$3, "style", _v$, _p$.e));
|
|
40837
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$5, "style", _v$2, _p$.t));
|
|
40838
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$7, "style", _v$3, _p$.a));
|
|
40839
|
+
return _p$;
|
|
40840
|
+
}, {
|
|
40841
|
+
e: undefined,
|
|
40842
|
+
t: undefined,
|
|
40843
|
+
a: undefined
|
|
40844
|
+
});
|
|
40845
|
+
return _el$2;
|
|
40846
|
+
}
|
|
40847
|
+
});
|
|
40848
|
+
}
|
|
40849
|
+
}), null);
|
|
40772
40850
|
insert(_el$, createComponent2(Show, {
|
|
40773
40851
|
get when() {
|
|
40774
40852
|
return error();
|
|
40775
40853
|
},
|
|
40776
40854
|
get children() {
|
|
40777
|
-
var _el$
|
|
40778
|
-
insertNode(_el$
|
|
40779
|
-
setProp(_el$
|
|
40780
|
-
insert(_el$
|
|
40781
|
-
effect((_$p) => setProp(_el$
|
|
40782
|
-
return _el$
|
|
40855
|
+
var _el$8 = createElement("text"), _el$9 = createTextNode(` `);
|
|
40856
|
+
insertNode(_el$8, _el$9);
|
|
40857
|
+
setProp(_el$8, "marginTop", 1);
|
|
40858
|
+
insert(_el$8, error, null);
|
|
40859
|
+
effect((_$p) => setProp(_el$8, "fg", COLORS.error, _$p));
|
|
40860
|
+
return _el$8;
|
|
40783
40861
|
}
|
|
40784
40862
|
}), null);
|
|
40785
40863
|
return _el$;
|
|
@@ -40800,7 +40878,6 @@ var SWEEP_CHARS = ["\u2591", "\u2592", "\u2593", "\u2588", "\u2593", "\u2592", "
|
|
|
40800
40878
|
var BAR_WIDTH = 6;
|
|
40801
40879
|
function SweepBar(props) {
|
|
40802
40880
|
const glow = SWEEP_CHARS.length;
|
|
40803
|
-
const totalWidth = BAR_WIDTH * 2 + props.title.length + 2;
|
|
40804
40881
|
const [pos, setPos] = createSignal(0);
|
|
40805
40882
|
createEffect(() => {
|
|
40806
40883
|
const interval = setInterval(() => setPos((p) => (p + 1) % (BAR_WIDTH + glow)), 50);
|
|
@@ -40876,22 +40953,105 @@ function useDiscoColor() {
|
|
|
40876
40953
|
});
|
|
40877
40954
|
return () => PARTY_COLORS[idx()];
|
|
40878
40955
|
}
|
|
40956
|
+
function personaToEntry(agent) {
|
|
40957
|
+
const env2 = agent.env ?? {};
|
|
40958
|
+
return {
|
|
40959
|
+
name: agent.name,
|
|
40960
|
+
tag: agent.tag,
|
|
40961
|
+
model: agent.model,
|
|
40962
|
+
provider: agent.provider,
|
|
40963
|
+
active: agent.active !== false,
|
|
40964
|
+
authUrl: env2.AUTH_URL ?? "",
|
|
40965
|
+
authToken: env2.AUTH_TOKEN ?? "",
|
|
40966
|
+
cli: agent.cli ?? "claude",
|
|
40967
|
+
prompts: agent.prompts,
|
|
40968
|
+
preloadSkills: agent.preloadSkills,
|
|
40969
|
+
executablePath: agent.executablePath,
|
|
40970
|
+
timeout: agent.timeout,
|
|
40971
|
+
extraEnv: extractExtraEnv(env2)
|
|
40972
|
+
};
|
|
40973
|
+
}
|
|
40974
|
+
function extractExtraEnv(env2) {
|
|
40975
|
+
const extra = {};
|
|
40976
|
+
for (const [k2, v2] of Object.entries(env2)) {
|
|
40977
|
+
if (k2 !== "AUTH_URL" && k2 !== "AUTH_TOKEN") {
|
|
40978
|
+
extra[k2] = v2;
|
|
40979
|
+
}
|
|
40980
|
+
}
|
|
40981
|
+
return Object.keys(extra).length > 0 ? extra : undefined;
|
|
40982
|
+
}
|
|
40983
|
+
function entryToPersona(entry) {
|
|
40984
|
+
const config = {
|
|
40985
|
+
name: entry.name.trim(),
|
|
40986
|
+
tag: entry.tag.trim(),
|
|
40987
|
+
provider: entry.provider,
|
|
40988
|
+
model: entry.model.trim(),
|
|
40989
|
+
active: entry.active
|
|
40990
|
+
};
|
|
40991
|
+
if (entry.provider === "custom") {
|
|
40992
|
+
config.cli = entry.cli || "claude";
|
|
40993
|
+
const env2 = {};
|
|
40994
|
+
if (entry.authUrl)
|
|
40995
|
+
env2.AUTH_URL = entry.authUrl;
|
|
40996
|
+
if (entry.authToken)
|
|
40997
|
+
env2.AUTH_TOKEN = entry.authToken;
|
|
40998
|
+
if (entry.extraEnv)
|
|
40999
|
+
Object.assign(env2, entry.extraEnv);
|
|
41000
|
+
if (Object.keys(env2).length > 0)
|
|
41001
|
+
config.env = env2;
|
|
41002
|
+
}
|
|
41003
|
+
if (entry.prompts)
|
|
41004
|
+
config.prompts = entry.prompts;
|
|
41005
|
+
if (entry.preloadSkills)
|
|
41006
|
+
config.preloadSkills = entry.preloadSkills;
|
|
41007
|
+
if (entry.executablePath)
|
|
41008
|
+
config.executablePath = entry.executablePath;
|
|
41009
|
+
if (entry.timeout)
|
|
41010
|
+
config.timeout = entry.timeout;
|
|
41011
|
+
return config;
|
|
41012
|
+
}
|
|
40879
41013
|
function ConfigWizard(props) {
|
|
40880
41014
|
const [step, setStep] = createSignal("detect");
|
|
40881
41015
|
const [detection, setDetection] = createSignal([]);
|
|
40882
|
-
const [selectedIds, setSelectedIds] = createSignal([]);
|
|
40883
|
-
const [, setAgentConfigs] = createSignal([]);
|
|
40884
41016
|
const [activeTab, setActiveTab] = createSignal(0);
|
|
40885
41017
|
const [focusedField, setFocusedField] = createSignal(0);
|
|
40886
41018
|
const [error, setError] = createSignal("");
|
|
40887
41019
|
const [tick, setTick] = createSignal(0);
|
|
40888
|
-
|
|
40889
|
-
let
|
|
40890
|
-
|
|
40891
|
-
|
|
41020
|
+
const [customItems, setCustomItems] = createSignal([]);
|
|
41021
|
+
let agentEntries = [];
|
|
41022
|
+
let settingsData = {
|
|
41023
|
+
name: props.existingConfig?.humanName || userInfo2().username || "USER",
|
|
41024
|
+
tag: props.existingConfig?.humanTag || toTag(props.existingConfig?.humanName || userInfo2().username || "USER"),
|
|
41025
|
+
maxHops: String(props.existingConfig?.maxAutoHops ?? 15),
|
|
41026
|
+
timeout: String(props.existingConfig?.timeout ?? 600)
|
|
40892
41027
|
};
|
|
40893
41028
|
let cursorPos = 0;
|
|
40894
41029
|
const spinner = useSpinner();
|
|
41030
|
+
const tuiRenderer = useRenderer();
|
|
41031
|
+
createEffect(() => {
|
|
41032
|
+
const handlePaste = (event) => {
|
|
41033
|
+
if (step() !== "configure")
|
|
41034
|
+
return;
|
|
41035
|
+
const text = new TextDecoder().decode(event.bytes);
|
|
41036
|
+
if (!text)
|
|
41037
|
+
return;
|
|
41038
|
+
const cleaned = text.replace(/\n/g, "");
|
|
41039
|
+
if (!cleaned)
|
|
41040
|
+
return;
|
|
41041
|
+
const fieldValue = getCurrentFieldValue();
|
|
41042
|
+
const cursor = cursorPos;
|
|
41043
|
+
updateField(fieldValue.slice(0, cursor) + cleaned + fieldValue.slice(cursor), cursor + cleaned.length);
|
|
41044
|
+
};
|
|
41045
|
+
tuiRenderer.keyInput.on("paste", handlePaste);
|
|
41046
|
+
onCleanup(() => {
|
|
41047
|
+
tuiRenderer.keyInput.off("paste", handlePaste);
|
|
41048
|
+
});
|
|
41049
|
+
});
|
|
41050
|
+
createEffect(() => {
|
|
41051
|
+
const existing = props.existingConfig?.agents ?? [];
|
|
41052
|
+
const customs = existing.filter((a) => a.provider === "custom").map(personaToEntry);
|
|
41053
|
+
setCustomItems(customs);
|
|
41054
|
+
});
|
|
40895
41055
|
createEffect(() => {
|
|
40896
41056
|
detectProviders().then((results) => {
|
|
40897
41057
|
setDetection(results);
|
|
@@ -40901,103 +41061,255 @@ function ConfigWizard(props) {
|
|
|
40901
41061
|
setStep("providers");
|
|
40902
41062
|
});
|
|
40903
41063
|
});
|
|
40904
|
-
const
|
|
40905
|
-
|
|
40906
|
-
|
|
40907
|
-
|
|
40908
|
-
|
|
40909
|
-
|
|
40910
|
-
|
|
40911
|
-
|
|
40912
|
-
|
|
40913
|
-
|
|
40914
|
-
|
|
40915
|
-
|
|
40916
|
-
const ids = selectedIndices.map((i) => PROVIDERS[i].id);
|
|
40917
|
-
setSelectedIds(ids);
|
|
40918
|
-
const configs = ids.map((id) => {
|
|
40919
|
-
const def = PROVIDERS.find((p) => p.id === id);
|
|
40920
|
-
const existing = existingByProvider().get(id);
|
|
41064
|
+
const existingNative = () => {
|
|
41065
|
+
const map = new Map;
|
|
41066
|
+
for (const a of props.existingConfig?.agents ?? []) {
|
|
41067
|
+
if (a.provider !== "custom")
|
|
41068
|
+
map.set(a.provider, a);
|
|
41069
|
+
}
|
|
41070
|
+
return map;
|
|
41071
|
+
};
|
|
41072
|
+
const multiSelectItems = () => {
|
|
41073
|
+
const nativeItems = PROVIDERS.map((provider) => {
|
|
41074
|
+
const result = detection().find((d2) => d2.id === provider.id);
|
|
41075
|
+
const available = result?.available ?? false;
|
|
40921
41076
|
return {
|
|
40922
|
-
|
|
40923
|
-
|
|
40924
|
-
|
|
40925
|
-
model: existing?.model || def.defaultModel
|
|
41077
|
+
label: provider.displayName,
|
|
41078
|
+
description: available ? provider.description : provider.unavailableHint,
|
|
41079
|
+
disabled: !available
|
|
40926
41080
|
};
|
|
40927
41081
|
});
|
|
40928
|
-
|
|
40929
|
-
|
|
40930
|
-
|
|
41082
|
+
const customs = customItems();
|
|
41083
|
+
if (customs.length > 0) {
|
|
41084
|
+
nativeItems.push({
|
|
41085
|
+
label: "\u2500\u2500 Custom \u2500\u2500",
|
|
41086
|
+
description: "",
|
|
41087
|
+
disabled: true
|
|
41088
|
+
});
|
|
41089
|
+
}
|
|
41090
|
+
const customEntries = customs.map((c) => ({
|
|
41091
|
+
label: c.name,
|
|
41092
|
+
description: "custom provider"
|
|
40931
41093
|
}));
|
|
41094
|
+
return [...nativeItems, ...customEntries];
|
|
41095
|
+
};
|
|
41096
|
+
const initialSelected = () => {
|
|
41097
|
+
if (!props.existingConfig)
|
|
41098
|
+
return;
|
|
41099
|
+
const indices = [];
|
|
41100
|
+
const nativeMap = existingNative();
|
|
41101
|
+
PROVIDERS.forEach((p, i) => {
|
|
41102
|
+
const existing = nativeMap.get(p.id);
|
|
41103
|
+
if (existing && existing.active !== false)
|
|
41104
|
+
indices.push(i);
|
|
41105
|
+
});
|
|
41106
|
+
const customs = customItems();
|
|
41107
|
+
if (customs.length > 0) {
|
|
41108
|
+
const offset = PROVIDERS.length + 1;
|
|
41109
|
+
customs.forEach((c, i) => {
|
|
41110
|
+
if (c.active)
|
|
41111
|
+
indices.push(offset + i);
|
|
41112
|
+
});
|
|
41113
|
+
}
|
|
41114
|
+
return indices.length > 0 ? indices : undefined;
|
|
41115
|
+
};
|
|
41116
|
+
const handleAddCustom = (name) => {
|
|
41117
|
+
const entry = {
|
|
41118
|
+
name,
|
|
41119
|
+
tag: toTag(name),
|
|
41120
|
+
model: "",
|
|
41121
|
+
provider: "custom",
|
|
41122
|
+
active: true,
|
|
41123
|
+
authUrl: "",
|
|
41124
|
+
authToken: "",
|
|
41125
|
+
cli: "claude"
|
|
41126
|
+
};
|
|
41127
|
+
setCustomItems((prev) => [...prev, entry]);
|
|
41128
|
+
};
|
|
41129
|
+
const handleProviderConfirm = (selectedIndices) => {
|
|
41130
|
+
const nativeMap = existingNative();
|
|
41131
|
+
const customs = customItems();
|
|
41132
|
+
const hasCustoms = customs.length > 0;
|
|
41133
|
+
const customOffset = PROVIDERS.length + (hasCustoms ? 1 : 0);
|
|
41134
|
+
const entries = [];
|
|
41135
|
+
for (let i = 0;i < PROVIDERS.length; i++) {
|
|
41136
|
+
const def = PROVIDERS[i];
|
|
41137
|
+
const isSelected = selectedIndices.includes(i);
|
|
41138
|
+
const existing = nativeMap.get(def.id);
|
|
41139
|
+
if (isSelected || existing) {
|
|
41140
|
+
entries.push({
|
|
41141
|
+
name: existing?.name || def.displayName,
|
|
41142
|
+
tag: existing?.tag || def.defaultTag,
|
|
41143
|
+
model: existing?.model || def.defaultModel,
|
|
41144
|
+
provider: def.id,
|
|
41145
|
+
active: isSelected,
|
|
41146
|
+
authUrl: "",
|
|
41147
|
+
authToken: "",
|
|
41148
|
+
cli: "claude",
|
|
41149
|
+
prompts: existing?.prompts,
|
|
41150
|
+
preloadSkills: existing?.preloadSkills,
|
|
41151
|
+
executablePath: existing?.executablePath,
|
|
41152
|
+
timeout: existing?.timeout
|
|
41153
|
+
});
|
|
41154
|
+
}
|
|
41155
|
+
}
|
|
41156
|
+
for (let i = 0;i < customs.length; i++) {
|
|
41157
|
+
const isSelected = selectedIndices.includes(customOffset + i);
|
|
41158
|
+
entries.push({
|
|
41159
|
+
...customs[i],
|
|
41160
|
+
active: isSelected
|
|
41161
|
+
});
|
|
41162
|
+
}
|
|
41163
|
+
agentEntries = entries;
|
|
40932
41164
|
setActiveTab(0);
|
|
40933
41165
|
setFocusedField(0);
|
|
40934
|
-
cursorPos =
|
|
41166
|
+
cursorPos = settingsData.name.length;
|
|
40935
41167
|
setStep("configure");
|
|
40936
41168
|
};
|
|
40937
41169
|
const handleProviderCancel = () => {
|
|
40938
41170
|
if (props.onCancel)
|
|
40939
41171
|
props.onCancel();
|
|
40940
41172
|
};
|
|
40941
|
-
const
|
|
41173
|
+
const activeEntries = () => agentEntries.filter((e) => e.active);
|
|
41174
|
+
const isSettingsTab = () => activeTab() === 0;
|
|
40942
41175
|
const agentTabIndex = () => activeTab() - 1;
|
|
40943
|
-
const totalTabs = () => (
|
|
40944
|
-
const
|
|
41176
|
+
const totalTabs = () => activeEntries().length + 1;
|
|
41177
|
+
const isCustomAgent = () => {
|
|
41178
|
+
if (isSettingsTab())
|
|
41179
|
+
return false;
|
|
41180
|
+
const entry = activeEntries()[agentTabIndex()];
|
|
41181
|
+
return entry?.provider === "custom";
|
|
41182
|
+
};
|
|
41183
|
+
const maxFieldIndex = () => {
|
|
41184
|
+
if (isSettingsTab())
|
|
41185
|
+
return 3;
|
|
41186
|
+
return isCustomAgent() ? 4 : 2;
|
|
41187
|
+
};
|
|
41188
|
+
const getFieldValueForEntry = (entry, field) => {
|
|
41189
|
+
if (entry.provider === "custom") {
|
|
41190
|
+
return [entry.name, entry.tag, entry.model, entry.authUrl, entry.authToken][field];
|
|
41191
|
+
}
|
|
41192
|
+
return [entry.name, entry.tag, entry.model][field];
|
|
41193
|
+
};
|
|
41194
|
+
const getSettingsFieldValue = (field) => {
|
|
41195
|
+
return [settingsData.name, settingsData.tag, settingsData.maxHops, settingsData.timeout][field];
|
|
41196
|
+
};
|
|
41197
|
+
const getCurrentFieldValue = () => {
|
|
41198
|
+
if (isSettingsTab())
|
|
41199
|
+
return getSettingsFieldValue(focusedField());
|
|
41200
|
+
const entry = activeEntries()[agentTabIndex()];
|
|
41201
|
+
if (!entry)
|
|
41202
|
+
return "";
|
|
41203
|
+
return getFieldValueForEntry(entry, focusedField());
|
|
41204
|
+
};
|
|
41205
|
+
const updateField = (value, newCursor) => {
|
|
41206
|
+
if (isSettingsTab()) {
|
|
41207
|
+
if (focusedField() === 0)
|
|
41208
|
+
settingsData.name = value;
|
|
41209
|
+
else if (focusedField() === 1)
|
|
41210
|
+
settingsData.tag = value;
|
|
41211
|
+
else if (focusedField() === 2)
|
|
41212
|
+
settingsData.maxHops = value;
|
|
41213
|
+
else
|
|
41214
|
+
settingsData.timeout = value;
|
|
41215
|
+
} else {
|
|
41216
|
+
const entry = activeEntries()[agentTabIndex()];
|
|
41217
|
+
if (!entry)
|
|
41218
|
+
return;
|
|
41219
|
+
if (entry.provider === "custom") {
|
|
41220
|
+
if (focusedField() === 0)
|
|
41221
|
+
entry.name = value;
|
|
41222
|
+
else if (focusedField() === 1)
|
|
41223
|
+
entry.tag = value;
|
|
41224
|
+
else if (focusedField() === 2)
|
|
41225
|
+
entry.model = value;
|
|
41226
|
+
else if (focusedField() === 3)
|
|
41227
|
+
entry.authUrl = value;
|
|
41228
|
+
else
|
|
41229
|
+
entry.authToken = value;
|
|
41230
|
+
} else {
|
|
41231
|
+
if (focusedField() === 0)
|
|
41232
|
+
entry.name = value;
|
|
41233
|
+
else if (focusedField() === 1)
|
|
41234
|
+
entry.tag = value;
|
|
41235
|
+
else
|
|
41236
|
+
entry.model = value;
|
|
41237
|
+
}
|
|
41238
|
+
}
|
|
41239
|
+
cursorPos = newCursor;
|
|
41240
|
+
setError("");
|
|
41241
|
+
setTick((n) => n + 1);
|
|
41242
|
+
};
|
|
41243
|
+
const isTagField = () => focusedField() === 1;
|
|
41244
|
+
const isNumberField = () => isSettingsTab() && (focusedField() === 2 || focusedField() === 3);
|
|
40945
41245
|
const saveConfig = async () => {
|
|
40946
|
-
|
|
40947
|
-
|
|
40948
|
-
|
|
40949
|
-
|
|
41246
|
+
if (!settingsData.name.trim()) {
|
|
41247
|
+
setError("Name cannot be empty");
|
|
41248
|
+
return;
|
|
41249
|
+
}
|
|
41250
|
+
if (!settingsData.tag.trim()) {
|
|
41251
|
+
setError("Tag cannot be empty");
|
|
40950
41252
|
return;
|
|
40951
41253
|
}
|
|
40952
|
-
if (!
|
|
40953
|
-
setError("
|
|
41254
|
+
if (!TAG_PATTERN.test(settingsData.tag.trim())) {
|
|
41255
|
+
setError("Tag can only contain letters, numbers, hyphens, underscores");
|
|
40954
41256
|
return;
|
|
40955
41257
|
}
|
|
40956
|
-
|
|
40957
|
-
|
|
41258
|
+
const maxHops = parseInt(settingsData.maxHops, 10);
|
|
41259
|
+
if (isNaN(maxHops) || maxHops < 0) {
|
|
41260
|
+
setError("Max Hops must be 0 or a positive number");
|
|
40958
41261
|
return;
|
|
40959
41262
|
}
|
|
40960
|
-
|
|
40961
|
-
|
|
40962
|
-
|
|
41263
|
+
const timeout = parseInt(settingsData.timeout, 10);
|
|
41264
|
+
if (isNaN(timeout) || timeout < 0) {
|
|
41265
|
+
setError("Timeout must be 0 or a positive number");
|
|
41266
|
+
return;
|
|
41267
|
+
}
|
|
41268
|
+
const tags = new Set;
|
|
41269
|
+
tags.add(settingsData.tag.trim().toLowerCase());
|
|
41270
|
+
for (const entry of agentEntries) {
|
|
41271
|
+
if (!entry.name.trim()) {
|
|
41272
|
+
setError(`Name cannot be empty for an agent`);
|
|
40963
41273
|
return;
|
|
40964
41274
|
}
|
|
40965
|
-
if (!
|
|
40966
|
-
setError(`Tag cannot be empty for ${
|
|
41275
|
+
if (!entry.tag.trim()) {
|
|
41276
|
+
setError(`Tag cannot be empty for ${entry.name}`);
|
|
40967
41277
|
return;
|
|
40968
41278
|
}
|
|
40969
|
-
if (!TAG_PATTERN.test(
|
|
40970
|
-
setError(`Tag for ${
|
|
41279
|
+
if (!TAG_PATTERN.test(entry.tag.trim())) {
|
|
41280
|
+
setError(`Tag for ${entry.name} can only contain letters, numbers, hyphens, underscores`);
|
|
40971
41281
|
return;
|
|
40972
41282
|
}
|
|
40973
|
-
if (!
|
|
40974
|
-
setError(`Model cannot be empty for ${
|
|
41283
|
+
if (!entry.model.trim()) {
|
|
41284
|
+
setError(`Model cannot be empty for ${entry.name}`);
|
|
40975
41285
|
return;
|
|
40976
41286
|
}
|
|
40977
|
-
|
|
40978
|
-
|
|
40979
|
-
|
|
40980
|
-
|
|
40981
|
-
|
|
40982
|
-
|
|
41287
|
+
const tagLower = entry.tag.trim().toLowerCase();
|
|
41288
|
+
if (tags.has(tagLower)) {
|
|
41289
|
+
setError(`Duplicate tag: ${entry.tag}`);
|
|
41290
|
+
return;
|
|
41291
|
+
}
|
|
41292
|
+
tags.add(tagLower);
|
|
41293
|
+
if (entry.provider === "custom" && entry.active && !entry.authUrl.trim()) {
|
|
41294
|
+
setError(`URL is required for ${entry.name}`);
|
|
40983
41295
|
return;
|
|
40984
41296
|
}
|
|
40985
|
-
names.add(lower);
|
|
40986
41297
|
}
|
|
40987
|
-
const
|
|
40988
|
-
|
|
40989
|
-
|
|
40990
|
-
|
|
40991
|
-
|
|
40992
|
-
|
|
40993
|
-
|
|
40994
|
-
|
|
40995
|
-
humanName: human.name.trim(),
|
|
40996
|
-
humanTag: human.tag.trim(),
|
|
40997
|
-
agents: props.existingConfig?.agents || []
|
|
41298
|
+
const agents = agentEntries.map(entryToPersona);
|
|
41299
|
+
const config = {
|
|
41300
|
+
humanName: settingsData.name.trim(),
|
|
41301
|
+
humanTag: settingsData.tag.trim(),
|
|
41302
|
+
maxAutoHops: maxHops,
|
|
41303
|
+
timeout: timeout > 0 ? timeout : undefined,
|
|
41304
|
+
reminderInterval: props.existingConfig?.reminderInterval,
|
|
41305
|
+
agents
|
|
40998
41306
|
};
|
|
41307
|
+
if (config.timeout === undefined)
|
|
41308
|
+
delete config.timeout;
|
|
41309
|
+
if (config.reminderInterval === undefined)
|
|
41310
|
+
delete config.reminderInterval;
|
|
40999
41311
|
try {
|
|
41000
|
-
await
|
|
41312
|
+
await writeConfig(config);
|
|
41001
41313
|
setStep("done");
|
|
41002
41314
|
} catch (err) {
|
|
41003
41315
|
setError(`Failed to save: ${err.message}`);
|
|
@@ -41009,9 +41321,8 @@ function ConfigWizard(props) {
|
|
|
41009
41321
|
return;
|
|
41010
41322
|
}
|
|
41011
41323
|
if (step() !== "configure") {
|
|
41012
|
-
if (step() === "detect")
|
|
41324
|
+
if (step() === "detect")
|
|
41013
41325
|
return;
|
|
41014
|
-
}
|
|
41015
41326
|
if (step() === "done") {
|
|
41016
41327
|
if (key.name === "enter" || key.name === "return" || key.name === "space") {
|
|
41017
41328
|
props.onComplete();
|
|
@@ -41020,49 +41331,20 @@ function ConfigWizard(props) {
|
|
|
41020
41331
|
}
|
|
41021
41332
|
return;
|
|
41022
41333
|
}
|
|
41023
|
-
const
|
|
41024
|
-
const human = humanData;
|
|
41025
|
-
let fieldValue;
|
|
41026
|
-
if (isYouTab()) {
|
|
41027
|
-
fieldValue = focusedField() === 0 ? human.name : human.tag;
|
|
41028
|
-
} else {
|
|
41029
|
-
const current = configs[agentTabIndex()];
|
|
41030
|
-
if (!current)
|
|
41031
|
-
return;
|
|
41032
|
-
fieldValue = [current.name, current.tag, current.model][focusedField()];
|
|
41033
|
-
}
|
|
41334
|
+
const fieldValue = getCurrentFieldValue();
|
|
41034
41335
|
const cursor = cursorPos;
|
|
41035
|
-
const updateField = (value, newCursor) => {
|
|
41036
|
-
if (isYouTab()) {
|
|
41037
|
-
if (focusedField() === 0)
|
|
41038
|
-
human.name = value;
|
|
41039
|
-
else
|
|
41040
|
-
human.tag = value;
|
|
41041
|
-
} else {
|
|
41042
|
-
const current = configs[agentTabIndex()];
|
|
41043
|
-
if (focusedField() === 0)
|
|
41044
|
-
current.name = value;
|
|
41045
|
-
else if (focusedField() === 1)
|
|
41046
|
-
current.tag = value;
|
|
41047
|
-
else
|
|
41048
|
-
current.model = value;
|
|
41049
|
-
}
|
|
41050
|
-
cursorPos = newCursor;
|
|
41051
|
-
setError("");
|
|
41052
|
-
setTick((n) => n + 1);
|
|
41053
|
-
};
|
|
41054
41336
|
if (key.sequence === "[" || key.sequence === "]") {
|
|
41055
41337
|
const dir = key.sequence === "[" ? -1 : 1;
|
|
41056
41338
|
const next = (activeTab() + dir + totalTabs()) % totalTabs();
|
|
41057
41339
|
setActiveTab(next);
|
|
41058
|
-
const newMax = next === 0 ? 1 : 2;
|
|
41340
|
+
const newMax = next === 0 ? 3 : activeEntries()[next - 1]?.provider === "custom" ? 4 : 2;
|
|
41059
41341
|
const newField = Math.min(focusedField(), newMax);
|
|
41060
41342
|
setFocusedField(newField);
|
|
41061
41343
|
let newVal;
|
|
41062
41344
|
if (next === 0) {
|
|
41063
|
-
newVal = newField
|
|
41345
|
+
newVal = getSettingsFieldValue(newField);
|
|
41064
41346
|
} else {
|
|
41065
|
-
newVal =
|
|
41347
|
+
newVal = getFieldValueForEntry(activeEntries()[next - 1], newField);
|
|
41066
41348
|
}
|
|
41067
41349
|
cursorPos = newVal.length;
|
|
41068
41350
|
setTick((n) => n + 1);
|
|
@@ -41072,12 +41354,7 @@ function ConfigWizard(props) {
|
|
|
41072
41354
|
const fieldCount = maxFieldIndex() + 1;
|
|
41073
41355
|
const nextField = key.shift ? (focusedField() - 1 + fieldCount) % fieldCount : (focusedField() + 1) % fieldCount;
|
|
41074
41356
|
setFocusedField(nextField);
|
|
41075
|
-
|
|
41076
|
-
if (isYouTab()) {
|
|
41077
|
-
newVal = nextField === 0 ? human.name : human.tag;
|
|
41078
|
-
} else {
|
|
41079
|
-
newVal = getFieldValue(configs[agentTabIndex()], nextField);
|
|
41080
|
-
}
|
|
41357
|
+
const newVal = isSettingsTab() ? getSettingsFieldValue(nextField) : getFieldValueForEntry(activeEntries()[agentTabIndex()], nextField);
|
|
41081
41358
|
cursorPos = newVal.length;
|
|
41082
41359
|
setTick((n) => n + 1);
|
|
41083
41360
|
return;
|
|
@@ -41132,7 +41409,7 @@ function ConfigWizard(props) {
|
|
|
41132
41409
|
return;
|
|
41133
41410
|
}
|
|
41134
41411
|
if (key.name === "space" || key.sequence === " ") {
|
|
41135
|
-
if (
|
|
41412
|
+
if (!isTagField() && !isNumberField()) {
|
|
41136
41413
|
updateField(fieldValue.slice(0, cursor) + " " + fieldValue.slice(cursor), cursor + 1);
|
|
41137
41414
|
}
|
|
41138
41415
|
return;
|
|
@@ -41141,7 +41418,9 @@ function ConfigWizard(props) {
|
|
|
41141
41418
|
if (ch && ch.length > 0 && !ch.startsWith("\x1B")) {
|
|
41142
41419
|
if (ch === "'" || ch === '"' || ch === "`")
|
|
41143
41420
|
return;
|
|
41144
|
-
if (
|
|
41421
|
+
if (isTagField() && !TAG_PATTERN.test(ch))
|
|
41422
|
+
return;
|
|
41423
|
+
if (isNumberField() && !/^[0-9]$/.test(ch))
|
|
41145
41424
|
return;
|
|
41146
41425
|
updateField(fieldValue.slice(0, cursor) + ch + fieldValue.slice(cursor), cursor + ch.length);
|
|
41147
41426
|
}
|
|
@@ -41159,7 +41438,7 @@ function ConfigWizard(props) {
|
|
|
41159
41438
|
})();
|
|
41160
41439
|
}
|
|
41161
41440
|
const discoColor = useDiscoColor();
|
|
41162
|
-
function renderField(label, value, isFocused) {
|
|
41441
|
+
function renderField(label, value, isFocused, hint) {
|
|
41163
41442
|
tick();
|
|
41164
41443
|
const cursor = cursorPos;
|
|
41165
41444
|
const labelColor = isFocused ? COLORS.primary : COLORS.textDim;
|
|
@@ -41182,7 +41461,7 @@ function ConfigWizard(props) {
|
|
|
41182
41461
|
setProp(_el$12, "style", {
|
|
41183
41462
|
fg: valueColor
|
|
41184
41463
|
});
|
|
41185
|
-
insert(_el$12, value);
|
|
41464
|
+
insert(_el$12, value || (hint ? hint : ""));
|
|
41186
41465
|
effect((_$p) => setProp(_el$0, "style", {
|
|
41187
41466
|
fg: COLORS.borderStrong
|
|
41188
41467
|
}, _$p));
|
|
@@ -41217,6 +41496,13 @@ function ConfigWizard(props) {
|
|
|
41217
41496
|
return _el$13;
|
|
41218
41497
|
})();
|
|
41219
41498
|
}
|
|
41499
|
+
function renderTokenField(label, value, isFocused) {
|
|
41500
|
+
if (!isFocused && value.length > 0) {
|
|
41501
|
+
const masked = value.length > 4 ? "*".repeat(value.length - 4) + value.slice(-4) : "*".repeat(value.length);
|
|
41502
|
+
return renderField(label, masked, false);
|
|
41503
|
+
}
|
|
41504
|
+
return renderField(label, value, isFocused);
|
|
41505
|
+
}
|
|
41220
41506
|
const DetectStep = () => (() => {
|
|
41221
41507
|
var _el$19 = createElement("box"), _el$20 = createElement("box"), _el$21 = createElement("box"), _el$22 = createElement("text"), _el$23 = createTextNode(` Scanning for installed CLIs...`);
|
|
41222
41508
|
insertNode(_el$19, _el$20);
|
|
@@ -41332,6 +41618,9 @@ function ConfigWizard(props) {
|
|
|
41332
41618
|
},
|
|
41333
41619
|
get initialSelected() {
|
|
41334
41620
|
return initialSelected();
|
|
41621
|
+
},
|
|
41622
|
+
addCustom: {
|
|
41623
|
+
onAdd: handleAddCustom
|
|
41335
41624
|
}
|
|
41336
41625
|
}));
|
|
41337
41626
|
effect((_p$) => {
|
|
@@ -41369,12 +41658,8 @@ function ConfigWizard(props) {
|
|
|
41369
41658
|
})();
|
|
41370
41659
|
const ConfigureStep = () => {
|
|
41371
41660
|
tick();
|
|
41372
|
-
const
|
|
41373
|
-
const
|
|
41374
|
-
const tabLabels = ["You", ...selectedIds().map((id) => {
|
|
41375
|
-
const def = PROVIDERS.find((p) => p.id === id);
|
|
41376
|
-
return def?.displayName || id;
|
|
41377
|
-
})];
|
|
41661
|
+
const active = activeEntries();
|
|
41662
|
+
const tabLabels = ["Settings", ...active.map((e) => e.name)];
|
|
41378
41663
|
return (() => {
|
|
41379
41664
|
var _el$48 = createElement("box"), _el$49 = createElement("box"), _el$50 = createElement("box"), _el$51 = createElement("box"), _el$52 = createElement("box"), _el$53 = createElement("text"), _el$55 = createElement("box"), _el$56 = createElement("box"), _el$60 = createElement("box"), _el$61 = createElement("text"), _el$62 = createElement("span"), _el$64 = createElement("span"), _el$66 = createElement("span"), _el$68 = createElement("span"), _el$70 = createElement("span"), _el$72 = createElement("span"), _el$74 = createElement("span"), _el$76 = createElement("span"), _el$78 = createElement("span"), _el$80 = createElement("span"), _el$82 = createElement("span"), _el$84 = createElement("span"), _el$86 = createElement("span");
|
|
41380
41665
|
insertNode(_el$48, _el$49);
|
|
@@ -41446,7 +41731,7 @@ function ConfigWizard(props) {
|
|
|
41446
41731
|
setProp(_el$56, "flexDirection", "column");
|
|
41447
41732
|
insert(_el$56, createComponent2(Show, {
|
|
41448
41733
|
get when() {
|
|
41449
|
-
return
|
|
41734
|
+
return isSettingsTab();
|
|
41450
41735
|
},
|
|
41451
41736
|
get fallback() {
|
|
41452
41737
|
return [(() => {
|
|
@@ -41455,19 +41740,39 @@ function ConfigWizard(props) {
|
|
|
41455
41740
|
setProp(_el$94, "marginBottom", 1);
|
|
41456
41741
|
insertNode(_el$95, _el$96);
|
|
41457
41742
|
insert(_el$95, () => tabLabels[activeTab()], _el$96);
|
|
41743
|
+
insert(_el$94, createComponent2(Show, {
|
|
41744
|
+
get when() {
|
|
41745
|
+
return activeEntries()[agentTabIndex()]?.provider === "custom";
|
|
41746
|
+
},
|
|
41747
|
+
get children() {
|
|
41748
|
+
var _el$97 = createElement("span");
|
|
41749
|
+
insertNode(_el$97, createTextNode(` (custom)`));
|
|
41750
|
+
effect((_$p) => setProp(_el$97, "style", {
|
|
41751
|
+
fg: COLORS.textFaint
|
|
41752
|
+
}, _$p));
|
|
41753
|
+
return _el$97;
|
|
41754
|
+
}
|
|
41755
|
+
}), null);
|
|
41458
41756
|
effect((_$p) => setProp(_el$94, "fg", COLORS.success, _$p));
|
|
41459
41757
|
return _el$94;
|
|
41460
|
-
})(), memo2(() => renderField("Name ",
|
|
41758
|
+
})(), memo2(() => renderField("Name ", active[agentTabIndex()].name, focusedField() === 0)), memo2(() => renderField("Tag ", active[agentTabIndex()].tag, focusedField() === 1)), memo2(() => renderField("Model", active[agentTabIndex()].model, focusedField() === 2)), createComponent2(Show, {
|
|
41759
|
+
get when() {
|
|
41760
|
+
return active[agentTabIndex()]?.provider === "custom";
|
|
41761
|
+
},
|
|
41762
|
+
get children() {
|
|
41763
|
+
return [memo2(() => renderField("URL ", active[agentTabIndex()].authUrl, focusedField() === 3)), memo2(() => renderTokenField("Token", active[agentTabIndex()].authToken, focusedField() === 4))];
|
|
41764
|
+
}
|
|
41765
|
+
})];
|
|
41461
41766
|
},
|
|
41462
41767
|
get children() {
|
|
41463
41768
|
return [(() => {
|
|
41464
41769
|
var _el$57 = createElement("text"), _el$58 = createElement("strong");
|
|
41465
41770
|
insertNode(_el$57, _el$58);
|
|
41466
41771
|
setProp(_el$57, "marginBottom", 1);
|
|
41467
|
-
insertNode(_el$58, createTextNode(`
|
|
41772
|
+
insertNode(_el$58, createTextNode(`General Settings`));
|
|
41468
41773
|
effect((_$p) => setProp(_el$57, "fg", COLORS.agent, _$p));
|
|
41469
41774
|
return _el$57;
|
|
41470
|
-
})(), memo2(() => renderField("Name",
|
|
41775
|
+
})(), memo2(() => renderField("Name ", settingsData.name, focusedField() === 0)), memo2(() => renderField("Tag ", settingsData.tag, focusedField() === 1)), memo2(() => renderField("Max Hops", settingsData.maxHops, focusedField() === 2, "0 = unlimited")), memo2(() => renderField("Timeout ", settingsData.timeout, focusedField() === 3, "0 = unlimited"))];
|
|
41471
41776
|
}
|
|
41472
41777
|
}));
|
|
41473
41778
|
insertNode(_el$60, _el$61);
|
|
@@ -41527,7 +41832,7 @@ function ConfigWizard(props) {
|
|
|
41527
41832
|
}
|
|
41528
41833
|
}), null);
|
|
41529
41834
|
effect((_p$) => {
|
|
41530
|
-
var _v$13 = discoColor(), _v$14 = COLORS.bgPanel, _v$15 = COLORS.borderStrong, _v$16 =
|
|
41835
|
+
var _v$13 = discoColor(), _v$14 = COLORS.bgPanel, _v$15 = COLORS.borderStrong, _v$16 = isSettingsTab() ? COLORS.agent : COLORS.success, _v$17 = COLORS.bgContent, _v$18 = {
|
|
41531
41836
|
fg: COLORS.textFaint
|
|
41532
41837
|
}, _v$19 = {
|
|
41533
41838
|
fg: COLORS.success
|
|
@@ -41597,57 +41902,57 @@ function ConfigWizard(props) {
|
|
|
41597
41902
|
})();
|
|
41598
41903
|
};
|
|
41599
41904
|
const DoneStep = () => (() => {
|
|
41600
|
-
var _el$
|
|
41601
|
-
insertNode(_el$97, _el$98);
|
|
41602
|
-
setProp(_el$97, "flexDirection", "column");
|
|
41603
|
-
setProp(_el$97, "width", "100%");
|
|
41604
|
-
setProp(_el$97, "height", "100%");
|
|
41605
|
-
setProp(_el$97, "justifyContent", "center");
|
|
41606
|
-
setProp(_el$97, "alignItems", "center");
|
|
41607
|
-
insertNode(_el$98, _el$99);
|
|
41608
|
-
setProp(_el$98, "border", true);
|
|
41609
|
-
setProp(_el$98, "borderStyle", "double");
|
|
41610
|
-
setProp(_el$98, "paddingX", 4);
|
|
41611
|
-
setProp(_el$98, "paddingY", 2);
|
|
41905
|
+
var _el$99 = createElement("box"), _el$100 = createElement("box"), _el$101 = createElement("box"), _el$102 = createElement("text"), _el$104 = createElement("text"), _el$106 = createElement("text"), _el$108 = createElement("text"), _el$110 = createElement("text"), _el$112 = createElement("text"), _el$113 = createTextNode(`Press `), _el$114 = createElement("span"), _el$115 = createElement("strong"), _el$117 = createTextNode(` to continue`);
|
|
41612
41906
|
insertNode(_el$99, _el$100);
|
|
41613
|
-
insertNode(_el$99, _el$102);
|
|
41614
|
-
insertNode(_el$99, _el$104);
|
|
41615
|
-
insertNode(_el$99, _el$106);
|
|
41616
|
-
insertNode(_el$99, _el$108);
|
|
41617
|
-
insertNode(_el$99, _el$110);
|
|
41618
41907
|
setProp(_el$99, "flexDirection", "column");
|
|
41908
|
+
setProp(_el$99, "width", "100%");
|
|
41909
|
+
setProp(_el$99, "height", "100%");
|
|
41910
|
+
setProp(_el$99, "justifyContent", "center");
|
|
41619
41911
|
setProp(_el$99, "alignItems", "center");
|
|
41620
|
-
|
|
41912
|
+
insertNode(_el$100, _el$101);
|
|
41913
|
+
setProp(_el$100, "border", true);
|
|
41914
|
+
setProp(_el$100, "borderStyle", "double");
|
|
41915
|
+
setProp(_el$100, "paddingX", 4);
|
|
41916
|
+
setProp(_el$100, "paddingY", 2);
|
|
41917
|
+
insertNode(_el$101, _el$102);
|
|
41918
|
+
insertNode(_el$101, _el$104);
|
|
41919
|
+
insertNode(_el$101, _el$106);
|
|
41920
|
+
insertNode(_el$101, _el$108);
|
|
41921
|
+
insertNode(_el$101, _el$110);
|
|
41922
|
+
insertNode(_el$101, _el$112);
|
|
41923
|
+
setProp(_el$101, "flexDirection", "column");
|
|
41924
|
+
setProp(_el$101, "alignItems", "center");
|
|
41925
|
+
insert(_el$101, createComponent2(SweepBar, {
|
|
41621
41926
|
title: "Config Saved"
|
|
41622
|
-
}), _el$
|
|
41623
|
-
insertNode(_el$
|
|
41624
|
-
setProp(_el$100, "marginTop", 1);
|
|
41625
|
-
insertNode(_el$102, createTextNode(`Written to ~/.llm-party/config.json`));
|
|
41927
|
+
}), _el$102);
|
|
41928
|
+
insertNode(_el$102, 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`));
|
|
41626
41929
|
setProp(_el$102, "marginTop", 1);
|
|
41627
|
-
insertNode(_el$104, createTextNode(`
|
|
41930
|
+
insertNode(_el$104, createTextNode(`Written to ~/.llm-party/config.json`));
|
|
41628
41931
|
setProp(_el$104, "marginTop", 1);
|
|
41629
|
-
insertNode(_el$106, createTextNode(`
|
|
41630
|
-
|
|
41631
|
-
|
|
41632
|
-
insertNode(_el$110,
|
|
41633
|
-
insertNode(_el$110, _el$112);
|
|
41634
|
-
insertNode(_el$110, _el$115);
|
|
41932
|
+
insertNode(_el$106, createTextNode(`Edit this file anytime to add prompts,`));
|
|
41933
|
+
setProp(_el$106, "marginTop", 1);
|
|
41934
|
+
insertNode(_el$108, createTextNode(`env vars, or tweak settings.`));
|
|
41935
|
+
insertNode(_el$110, 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`));
|
|
41635
41936
|
setProp(_el$110, "marginTop", 1);
|
|
41636
41937
|
insertNode(_el$112, _el$113);
|
|
41637
|
-
insertNode(_el$
|
|
41938
|
+
insertNode(_el$112, _el$114);
|
|
41939
|
+
insertNode(_el$112, _el$117);
|
|
41940
|
+
setProp(_el$112, "marginTop", 1);
|
|
41941
|
+
insertNode(_el$114, _el$115);
|
|
41942
|
+
insertNode(_el$115, createTextNode(`Enter`));
|
|
41638
41943
|
effect((_p$) => {
|
|
41639
41944
|
var _v$33 = discoColor(), _v$34 = COLORS.bgPanel, _v$35 = COLORS.textSubtle, _v$36 = COLORS.textMuted, _v$37 = COLORS.textSubtle, _v$38 = COLORS.textSubtle, _v$39 = COLORS.textSubtle, _v$40 = COLORS.primary, _v$41 = {
|
|
41640
41945
|
fg: COLORS.success
|
|
41641
41946
|
};
|
|
41642
|
-
_v$33 !== _p$.e && (_p$.e = setProp(_el$
|
|
41643
|
-
_v$34 !== _p$.t && (_p$.t = setProp(_el$
|
|
41644
|
-
_v$35 !== _p$.a && (_p$.a = setProp(_el$
|
|
41645
|
-
_v$36 !== _p$.o && (_p$.o = setProp(_el$
|
|
41646
|
-
_v$37 !== _p$.i && (_p$.i = setProp(_el$
|
|
41647
|
-
_v$38 !== _p$.n && (_p$.n = setProp(_el$
|
|
41648
|
-
_v$39 !== _p$.s && (_p$.s = setProp(_el$
|
|
41649
|
-
_v$40 !== _p$.h && (_p$.h = setProp(_el$
|
|
41650
|
-
_v$41 !== _p$.r && (_p$.r = setProp(_el$
|
|
41947
|
+
_v$33 !== _p$.e && (_p$.e = setProp(_el$100, "borderColor", _v$33, _p$.e));
|
|
41948
|
+
_v$34 !== _p$.t && (_p$.t = setProp(_el$100, "backgroundColor", _v$34, _p$.t));
|
|
41949
|
+
_v$35 !== _p$.a && (_p$.a = setProp(_el$102, "fg", _v$35, _p$.a));
|
|
41950
|
+
_v$36 !== _p$.o && (_p$.o = setProp(_el$104, "fg", _v$36, _p$.o));
|
|
41951
|
+
_v$37 !== _p$.i && (_p$.i = setProp(_el$106, "fg", _v$37, _p$.i));
|
|
41952
|
+
_v$38 !== _p$.n && (_p$.n = setProp(_el$108, "fg", _v$38, _p$.n));
|
|
41953
|
+
_v$39 !== _p$.s && (_p$.s = setProp(_el$110, "fg", _v$39, _p$.s));
|
|
41954
|
+
_v$40 !== _p$.h && (_p$.h = setProp(_el$112, "fg", _v$40, _p$.h));
|
|
41955
|
+
_v$41 !== _p$.r && (_p$.r = setProp(_el$114, "style", _v$41, _p$.r));
|
|
41651
41956
|
return _p$;
|
|
41652
41957
|
}, {
|
|
41653
41958
|
e: undefined,
|
|
@@ -41660,7 +41965,7 @@ function ConfigWizard(props) {
|
|
|
41660
41965
|
h: undefined,
|
|
41661
41966
|
r: undefined
|
|
41662
41967
|
});
|
|
41663
|
-
return _el$
|
|
41968
|
+
return _el$99;
|
|
41664
41969
|
})();
|
|
41665
41970
|
return [createComponent2(Show, {
|
|
41666
41971
|
get when() {
|
|
@@ -41692,13 +41997,6 @@ function ConfigWizard(props) {
|
|
|
41692
41997
|
}
|
|
41693
41998
|
})];
|
|
41694
41999
|
}
|
|
41695
|
-
function getFieldValue(config, field) {
|
|
41696
|
-
if (field === 0)
|
|
41697
|
-
return config.name;
|
|
41698
|
-
if (field === 1)
|
|
41699
|
-
return config.tag;
|
|
41700
|
-
return config.model;
|
|
41701
|
-
}
|
|
41702
42000
|
|
|
41703
42001
|
// src/ui/AgentsPanel.tsx
|
|
41704
42002
|
function AgentsPanel(props) {
|
|
@@ -42003,7 +42301,7 @@ function InfoPanel(props) {
|
|
|
42003
42301
|
|
|
42004
42302
|
// src/ui/App.tsx
|
|
42005
42303
|
function copyToClipboard(text) {
|
|
42006
|
-
const proc =
|
|
42304
|
+
const proc = spawn4("pbcopy", [], {
|
|
42007
42305
|
stdio: ["pipe", "ignore", "ignore"]
|
|
42008
42306
|
});
|
|
42009
42307
|
proc.stdin?.write(text);
|
|
@@ -42035,6 +42333,7 @@ function App(props) {
|
|
|
42035
42333
|
const agents = props.orchestrator.listAgents();
|
|
42036
42334
|
let scrollRef = null;
|
|
42037
42335
|
const [screen, setScreen] = createSignal("chat");
|
|
42336
|
+
const [freshConfig, setFreshConfig] = createSignal(props.config);
|
|
42038
42337
|
const [showAgents, setShowAgents] = createSignal(false);
|
|
42039
42338
|
const [showInfo, setShowInfo] = createSignal(false);
|
|
42040
42339
|
process.on("SIGINT", () => renderer.destroy());
|
|
@@ -42108,6 +42407,10 @@ Transcript: ${props.orchestrator.getTranscriptPath()}`);
|
|
|
42108
42407
|
return;
|
|
42109
42408
|
}
|
|
42110
42409
|
if (line === "/config") {
|
|
42410
|
+
try {
|
|
42411
|
+
const reloaded = await loadConfig2(props.configPath);
|
|
42412
|
+
setFreshConfig(reloaded);
|
|
42413
|
+
} catch {}
|
|
42111
42414
|
setScreen("config");
|
|
42112
42415
|
return;
|
|
42113
42416
|
}
|
|
@@ -42148,7 +42451,7 @@ ${lines.join(`
|
|
|
42148
42451
|
return createComponent2(ConfigWizard, {
|
|
42149
42452
|
isFirstRun: false,
|
|
42150
42453
|
get existingConfig() {
|
|
42151
|
-
return
|
|
42454
|
+
return freshConfig();
|
|
42152
42455
|
},
|
|
42153
42456
|
onComplete: () => {
|
|
42154
42457
|
addSystemMessage("Config saved. Restart llm-party to apply changes.");
|
|
@@ -42265,7 +42568,8 @@ async function bootApp(appRoot, rendererConfig) {
|
|
|
42265
42568
|
` + obsidianPrompt;
|
|
42266
42569
|
const availableSkills = await discoverSkills();
|
|
42267
42570
|
const agentVerifiedSkills = new Map;
|
|
42268
|
-
|
|
42571
|
+
const activeAgents = config.agents.filter((a) => a.active !== false);
|
|
42572
|
+
for (const agent of activeAgents) {
|
|
42269
42573
|
if (agent.preloadSkills && agent.preloadSkills.length > 0) {
|
|
42270
42574
|
const verified = [];
|
|
42271
42575
|
const report = [];
|
|
@@ -42286,7 +42590,7 @@ async function bootApp(appRoot, rendererConfig) {
|
|
|
42286
42590
|
const resolveFromConfig = (value) => {
|
|
42287
42591
|
return path11.isAbsolute(value) ? value : path11.resolve(configDir, value);
|
|
42288
42592
|
};
|
|
42289
|
-
const adapters = await Promise.all(
|
|
42593
|
+
const adapters = await Promise.all(activeAgents.map(async (agent, _index, allAgents) => {
|
|
42290
42594
|
const promptParts = [mergedBase];
|
|
42291
42595
|
if (agent.prompts && agent.prompts.length > 0) {
|
|
42292
42596
|
const extraPaths = agent.prompts.map((p) => resolveFromConfig(p));
|
|
@@ -42325,7 +42629,7 @@ ${mySkills.map((s) => `- ${s}`).join(`
|
|
|
42325
42629
|
agentCount: String(allAgents.length),
|
|
42326
42630
|
preloadedSkills
|
|
42327
42631
|
});
|
|
42328
|
-
const adapter = agent.provider === "claude" ? new ClaudeAdapter(agent.name, agent.model) : agent.provider === "codex" ? new CodexAdapter(agent.name, agent.model) : agent.provider === "copilot" ? new CopilotAdapter(agent.name, agent.model) : agent.provider === "
|
|
42632
|
+
const adapter = agent.provider === "claude" ? new ClaudeAdapter(agent.name, agent.model, humanName) : agent.provider === "codex" ? new CodexAdapter(agent.name, agent.model, humanName) : agent.provider === "copilot" ? new CopilotAdapter(agent.name, agent.model, humanName) : agent.provider === "custom" ? new CustomAdapter(agent.name, agent.model, humanName) : null;
|
|
42329
42633
|
if (!adapter) {
|
|
42330
42634
|
throw new Error(`Unsupported provider: ${agent.provider}`);
|
|
42331
42635
|
}
|
|
@@ -42333,12 +42637,12 @@ ${mySkills.map((s) => `- ${s}`).join(`
|
|
|
42333
42637
|
return adapter;
|
|
42334
42638
|
}));
|
|
42335
42639
|
const defaultTimeout = typeof config.timeout === "number" && config.timeout > 0 ? config.timeout * 1000 : 600000;
|
|
42336
|
-
const agentTimeouts = Object.fromEntries(
|
|
42337
|
-
const orchestrator = new Orchestrator(adapters, humanName, Object.fromEntries(
|
|
42338
|
-
await render(() => App({ orchestrator, maxAutoHops, config }), rendererConfig);
|
|
42640
|
+
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, maxAutoHops, config, configPath }), rendererConfig);
|
|
42339
42643
|
}
|
|
42340
42644
|
function resolveMaxAutoHops(value) {
|
|
42341
|
-
if (value === "
|
|
42645
|
+
if (typeof value === "number" && value === 0) {
|
|
42342
42646
|
return Number.POSITIVE_INFINITY;
|
|
42343
42647
|
}
|
|
42344
42648
|
if (typeof value === "number" && Number.isFinite(value) && value >= 1) {
|