farai 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1663 -145
- package/dist/cli/index.js.map +51 -45
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -810,9 +810,9 @@ class SqliteStore {
|
|
|
810
810
|
});
|
|
811
811
|
try {
|
|
812
812
|
ensurePrivateRegularFileIfExists(file, "farai database path");
|
|
813
|
+
db.exec("PRAGMA busy_timeout = 5000;");
|
|
813
814
|
db.exec("PRAGMA journal_mode = WAL;");
|
|
814
815
|
db.exec("PRAGMA foreign_keys = ON;");
|
|
815
|
-
db.exec("PRAGMA busy_timeout = 5000;");
|
|
816
816
|
this.migrate(db);
|
|
817
817
|
ensurePrivateSqlitePath(file, "farai database path");
|
|
818
818
|
this.db = db;
|
|
@@ -6436,6 +6436,7 @@ function normalizeConfig(raw) {
|
|
|
6436
6436
|
const email = providerMap(raw.email_accounts ?? raw.emailAccounts);
|
|
6437
6437
|
const modelLimits = modelLimitMap(raw.model_limits ?? raw.modelLimits);
|
|
6438
6438
|
const recent = raw.recent_models ?? raw.recentModels;
|
|
6439
|
+
const pinnedSkills = raw.pinned_skills ?? raw.pinnedSkills;
|
|
6439
6440
|
const proxy = proxyConfig(raw.proxy);
|
|
6440
6441
|
const context = contextConfig(raw.context);
|
|
6441
6442
|
const lsp = lspConfig(raw.lsp);
|
|
@@ -6477,6 +6478,9 @@ function normalizeConfig(raw) {
|
|
|
6477
6478
|
...Array.isArray(recent) ? {
|
|
6478
6479
|
recentModels: recent.filter((item) => typeof item === "string")
|
|
6479
6480
|
} : {},
|
|
6481
|
+
...Array.isArray(pinnedSkills) ? {
|
|
6482
|
+
pinnedSkills: [...new Set(pinnedSkills.filter((item) => typeof item === "string" && Boolean(item.trim())).map((item) => item.trim()))]
|
|
6483
|
+
} : {},
|
|
6480
6484
|
...modelLimits ? {
|
|
6481
6485
|
modelLimits
|
|
6482
6486
|
} : {},
|
|
@@ -6651,6 +6655,9 @@ function mergeConfig(base, over) {
|
|
|
6651
6655
|
...over.recentModels ?? base.recentModels ? {
|
|
6652
6656
|
recentModels: over.recentModels ?? base.recentModels
|
|
6653
6657
|
} : {},
|
|
6658
|
+
...base.pinnedSkills || over.pinnedSkills ? {
|
|
6659
|
+
pinnedSkills: [...new Set([...base.pinnedSkills ?? [], ...over.pinnedSkills ?? []])]
|
|
6660
|
+
} : {},
|
|
6654
6661
|
...base.modelLimits || over.modelLimits ? {
|
|
6655
6662
|
modelLimits: {
|
|
6656
6663
|
...base.modelLimits,
|
|
@@ -6721,6 +6728,8 @@ function serializeConfigToml(config) {
|
|
|
6721
6728
|
lines.push(`model = ${tomlString(config.model)}`);
|
|
6722
6729
|
if (config.recentModels?.length)
|
|
6723
6730
|
lines.push(`recent_models = ${tomlArray(config.recentModels)}`);
|
|
6731
|
+
if (config.pinnedSkills?.length)
|
|
6732
|
+
lines.push(`pinned_skills = ${tomlArray(config.pinnedSkills)}`);
|
|
6724
6733
|
if (config.contextWindow)
|
|
6725
6734
|
lines.push(`context_window = ${config.contextWindow}`);
|
|
6726
6735
|
if (config.maxOutputTokens)
|
|
@@ -9257,8 +9266,8 @@ var init_renderers = __esm(() => {
|
|
|
9257
9266
|
|
|
9258
9267
|
// src/version.ts
|
|
9259
9268
|
function resolveFaraiVersion() {
|
|
9260
|
-
if ("0.3.
|
|
9261
|
-
return "0.3.
|
|
9269
|
+
if ("0.3.9")
|
|
9270
|
+
return "0.3.9";
|
|
9262
9271
|
try {
|
|
9263
9272
|
const parsed = JSON.parse(readBoundedFileTextSync(new URL("../package.json", import.meta.url), 1024 * 1024, "package metadata"));
|
|
9264
9273
|
if (typeof parsed.version === "string" && parsed.version)
|
|
@@ -15640,49 +15649,50 @@ function buildDnsProbeCommand(args) {
|
|
|
15640
15649
|
const recordTypes = requested.length ? requested : ["a", "aaaa", "cname"];
|
|
15641
15650
|
if (recordTypes.some((value) => !DNS_RECORD_TYPES.includes(value)))
|
|
15642
15651
|
throw new Error("recordTypes contains an unsupported DNS record type");
|
|
15643
|
-
const
|
|
15644
|
-
for (const type of recordTypes)
|
|
15645
|
-
command.push(`-${type}`);
|
|
15646
|
-
if (args.includeAsn === true)
|
|
15647
|
-
command.push("-asn");
|
|
15652
|
+
const timeout = integer(args.timeoutSeconds, 5, 1, 30);
|
|
15648
15653
|
const resolvers = optionalStringList(args.resolvers, "resolvers", 100);
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
return
|
|
15654
|
+
const queries = names.flatMap((name) => recordTypes.map((type) => `${name} ${type.toUpperCase()}`));
|
|
15655
|
+
const queryLines = queries.map(shellQuote3).join(" ");
|
|
15656
|
+
const fixed = ["dig", "+noall", "+answer", "+nocomments", "+tries=1", `+time=${timeout}`].join(" ");
|
|
15657
|
+
const server = resolvers[0] ? ` ${shellQuote3(`@${resolvers[0]}`)}` : "";
|
|
15658
|
+
return ['file="$(mktemp /tmp/farai-dig.XXXXXX)" || exit 1', `trap 'rm -f "$file"' EXIT`, `printf '%s\\n' ${queryLines} > "$file"`, `${fixed}${server} -f "$file"`].join(`
|
|
15659
|
+
`);
|
|
15654
15660
|
}
|
|
15655
15661
|
function parseDnsProbeOutput(raw) {
|
|
15656
|
-
const
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
|
|
15667
|
-
|
|
15662
|
+
const byName = new Map;
|
|
15663
|
+
let malformed = 0;
|
|
15664
|
+
for (const line of raw.split(`
|
|
15665
|
+
`)) {
|
|
15666
|
+
const trimmed = line.trim();
|
|
15667
|
+
if (!trimmed || trimmed.startsWith(";"))
|
|
15668
|
+
continue;
|
|
15669
|
+
const fields = trimmed.split(/\s+/);
|
|
15670
|
+
if (fields.length < 5) {
|
|
15671
|
+
malformed += 1;
|
|
15672
|
+
continue;
|
|
15673
|
+
}
|
|
15674
|
+
const owner = fields[0].replace(/\.$/, "").toLowerCase();
|
|
15675
|
+
const type = fields[3].toLowerCase();
|
|
15676
|
+
const value = fields.slice(4).join(" ").replace(/\.$/, "");
|
|
15677
|
+
if (!DNS_RECORD_TYPES.includes(type))
|
|
15678
|
+
continue;
|
|
15679
|
+
const entry = byName.get(owner) ?? {};
|
|
15680
|
+
(entry[type] ??= []).push(value);
|
|
15681
|
+
byName.set(owner, entry);
|
|
15668
15682
|
}
|
|
15669
|
-
const
|
|
15670
|
-
|
|
15683
|
+
const records = [...byName.entries()].map(([name, entryRecords]) => ({
|
|
15684
|
+
name,
|
|
15685
|
+
records: entryRecords,
|
|
15686
|
+
resolver: []
|
|
15687
|
+
}));
|
|
15671
15688
|
return {
|
|
15672
|
-
name: text(value.host) ?? text(value.input) ?? "unknown",
|
|
15673
|
-
...status ? {
|
|
15674
|
-
status
|
|
15675
|
-
} : {},
|
|
15676
15689
|
records,
|
|
15677
|
-
|
|
15678
|
-
...asn ? {
|
|
15679
|
-
asn
|
|
15680
|
-
} : {}
|
|
15690
|
+
malformed
|
|
15681
15691
|
};
|
|
15682
15692
|
}
|
|
15683
15693
|
function renderDnsProbe(item) {
|
|
15684
15694
|
const answers = Object.entries(item.records).flatMap(([type, values]) => values.map((value) => `${type.toUpperCase()} ${value}`));
|
|
15685
|
-
return `${item.name}${
|
|
15695
|
+
return `${item.name}${answers.length ? ` \xB7 ${answers.join(" \xB7 ")}` : " \xB7 no answers"}`;
|
|
15686
15696
|
}
|
|
15687
15697
|
var DNS_RECORD_TYPES, dnsProbeTool;
|
|
15688
15698
|
var init_dns_probe = __esm(() => {
|
|
@@ -15693,7 +15703,7 @@ var init_dns_probe = __esm(() => {
|
|
|
15693
15703
|
DNS_RECORD_TYPES = ["a", "aaaa", "cname", "ns", "txt", "srv", "ptr", "mx", "soa", "caa"];
|
|
15694
15704
|
dnsProbeTool = {
|
|
15695
15705
|
name: "dns_resolve",
|
|
15696
|
-
description: "Resolve
|
|
15706
|
+
description: "Resolve one or many hostnames with dig using selected DNS record types and optional custom resolver. Returns answer records grouped by name (following CNAME targets as their own entries). Use this to validate candidates from asset_subdomains before HTTP or port probing; it is not a passive discovery source.",
|
|
15697
15707
|
inputSchema: {
|
|
15698
15708
|
type: "object",
|
|
15699
15709
|
required: ["names"],
|
|
@@ -15730,24 +15740,13 @@ var init_dns_probe = __esm(() => {
|
|
|
15730
15740
|
},
|
|
15731
15741
|
maxItems: 100,
|
|
15732
15742
|
uniqueItems: true
|
|
15733
|
-
}]
|
|
15734
|
-
|
|
15735
|
-
wildcard: {
|
|
15736
|
-
type: "string",
|
|
15737
|
-
enum: ["off", "auto"]
|
|
15738
|
-
},
|
|
15739
|
-
includeAsn: {
|
|
15740
|
-
type: "boolean"
|
|
15743
|
+
}],
|
|
15744
|
+
description: "optional custom resolver; the first entry is passed to dig as @resolver"
|
|
15741
15745
|
},
|
|
15742
15746
|
timeoutSeconds: {
|
|
15743
15747
|
type: "integer",
|
|
15744
15748
|
minimum: 1,
|
|
15745
15749
|
maximum: 30
|
|
15746
|
-
},
|
|
15747
|
-
rateLimit: {
|
|
15748
|
-
type: "integer",
|
|
15749
|
-
minimum: 1,
|
|
15750
|
-
maximum: 1e4
|
|
15751
15750
|
}
|
|
15752
15751
|
},
|
|
15753
15752
|
additionalProperties: false
|
|
@@ -15768,7 +15767,7 @@ var init_dns_probe = __esm(() => {
|
|
|
15768
15767
|
const parsed = parseDnsProbeOutput(result.stdout);
|
|
15769
15768
|
return projectDiscoveryResult(context, {
|
|
15770
15769
|
tool: "dns_resolve",
|
|
15771
|
-
backend: "
|
|
15770
|
+
backend: "dig",
|
|
15772
15771
|
result,
|
|
15773
15772
|
records: parsed.records,
|
|
15774
15773
|
malformed: parsed.malformed,
|
|
@@ -15783,11 +15782,29 @@ var init_dns_probe = __esm(() => {
|
|
|
15783
15782
|
});
|
|
15784
15783
|
|
|
15785
15784
|
// src/agent-tools/recon/http-probe.ts
|
|
15785
|
+
function hasScheme(target) {
|
|
15786
|
+
return /^[a-z][a-z0-9+.-]*:\/\//i.test(target);
|
|
15787
|
+
}
|
|
15788
|
+
function probeSchemes(args) {
|
|
15789
|
+
if (!Array.isArray(args.schemes))
|
|
15790
|
+
return ["https"];
|
|
15791
|
+
const schemes = [...new Set(args.schemes.filter((item) => item === "https" || item === "http"))];
|
|
15792
|
+
return schemes.length ? schemes : ["https"];
|
|
15793
|
+
}
|
|
15794
|
+
function fastProbeTargets(args) {
|
|
15795
|
+
const schemes = probeSchemes(args);
|
|
15796
|
+
return stringList(args.targets, "targets").flatMap((target) => hasScheme(target) ? [target] : schemes.map((scheme) => `${scheme}://${target}`));
|
|
15797
|
+
}
|
|
15798
|
+
function fastHttpProbeBudgetMs(args) {
|
|
15799
|
+
const timeoutSeconds = integer(args.timeoutSeconds, 3, 1, 15);
|
|
15800
|
+
const concurrency = integer(args.concurrency, 100, 1, 200);
|
|
15801
|
+
const waves = Math.max(1, Math.ceil(fastProbeTargets(args).length / concurrency));
|
|
15802
|
+
return Math.min(28000, Math.max(8000, waves * timeoutSeconds * 1000 + 6000));
|
|
15803
|
+
}
|
|
15786
15804
|
function buildFastHttpProbeCommand(args) {
|
|
15787
|
-
const targets = stringList(args.targets, "targets");
|
|
15788
15805
|
const timeoutSeconds = integer(args.timeoutSeconds, 3, 1, 15);
|
|
15789
15806
|
const concurrency = integer(args.concurrency, 100, 1, 200);
|
|
15790
|
-
const probeTargets =
|
|
15807
|
+
const probeTargets = fastProbeTargets(args);
|
|
15791
15808
|
const configLines = probeTargets.flatMap((target) => [`url = "${curlConfigQuote(target)}"`, 'output = "/dev/null"', 'write-out = "%{url}\\t%{url_effective}\\t%{http_code}\\t%{content_type}\\t%{size_download}\\t%{time_total}\\t%{remote_ip}\\t%{exitcode}\\t%{errormsg}\\n"']).map(shellQuote3).join(" ");
|
|
15792
15809
|
return ['config="$(mktemp /tmp/farai-http-probe.XXXXXX)" || exit 1', `trap 'rm -f "$config"' EXIT`, `printf '%s\\n' ${configLines} > "$config"`, `curl --parallel --parallel-immediate --parallel-max ${concurrency} --silent --show-error --insecure --connect-timeout 1 --max-time ${timeoutSeconds} --config "$config"`].join(`
|
|
15793
15810
|
`);
|
|
@@ -15986,7 +16003,7 @@ var init_http_probe = __esm(() => {
|
|
|
15986
16003
|
init_projectdiscovery();
|
|
15987
16004
|
httpProbeTool = {
|
|
15988
16005
|
name: "service_probe",
|
|
15989
|
-
description:
|
|
16006
|
+
description: 'Probe one or many hosts, IPs, or URLs with a lightweight concurrent HTTP probe and return normalized live service records. Fast mode (default) tries https only for bare hosts and returns status, content type, response size, address, and timing; pass schemes:["https","http"] to also probe http. Detail mode uses ProjectDiscovery httpx for page title, server, technology, ASN, CDN/WAF, redirect, and TLS enrichment. Use this after subdomain or port discovery; use browser tools for interactive state and http_request for one exact protocol request.',
|
|
15990
16007
|
inputSchema: {
|
|
15991
16008
|
type: "object",
|
|
15992
16009
|
required: ["targets"],
|
|
@@ -16020,6 +16037,17 @@ var init_http_probe = __esm(() => {
|
|
|
16020
16037
|
uniqueItems: true
|
|
16021
16038
|
}]
|
|
16022
16039
|
},
|
|
16040
|
+
schemes: {
|
|
16041
|
+
type: "array",
|
|
16042
|
+
items: {
|
|
16043
|
+
type: "string",
|
|
16044
|
+
enum: ["https", "http"]
|
|
16045
|
+
},
|
|
16046
|
+
minItems: 1,
|
|
16047
|
+
maxItems: 2,
|
|
16048
|
+
uniqueItems: true,
|
|
16049
|
+
description: 'schemes to try for bare hosts; defaults to https only for speed, pass ["https","http"] to also probe http'
|
|
16050
|
+
},
|
|
16023
16051
|
redirects: {
|
|
16024
16052
|
type: "string",
|
|
16025
16053
|
enum: ["none", "same_host", "all"]
|
|
@@ -16061,7 +16089,7 @@ var init_http_probe = __esm(() => {
|
|
|
16061
16089
|
assertObject(args, "args");
|
|
16062
16090
|
const kali = backend(context);
|
|
16063
16091
|
const detail = args.mode === "detail";
|
|
16064
|
-
const result = await kali.exec(buildHttpProbeCommand(args), detail ? 25000 :
|
|
16092
|
+
const result = await kali.exec(buildHttpProbeCommand(args), detail ? 25000 : fastHttpProbeBudgetMs(args), context.signal, 16000000);
|
|
16065
16093
|
const converted = timeoutBackgroundResult("service_probe", kali, result);
|
|
16066
16094
|
if (converted)
|
|
16067
16095
|
return converted;
|
|
@@ -19423,6 +19451,29 @@ function loadSkill(name, options = {}) {
|
|
|
19423
19451
|
}
|
|
19424
19452
|
};
|
|
19425
19453
|
}
|
|
19454
|
+
function renderPinnedSkills(workspace, names, maxChars = 24000) {
|
|
19455
|
+
const unique = [...new Set(names.map((name) => name.trim()).filter(Boolean))];
|
|
19456
|
+
if (!unique.length || maxChars < 200)
|
|
19457
|
+
return;
|
|
19458
|
+
const blocks = [];
|
|
19459
|
+
for (const name of unique) {
|
|
19460
|
+
const skill = loadSkill(name, {
|
|
19461
|
+
workspace
|
|
19462
|
+
});
|
|
19463
|
+
if (!skill)
|
|
19464
|
+
continue;
|
|
19465
|
+
blocks.push(`## pinned skill: ${skill.name}
|
|
19466
|
+
source: ${skill.source} \xB7 sha256: ${skill.hash}
|
|
19467
|
+
|
|
19468
|
+
${skill.body}`);
|
|
19469
|
+
}
|
|
19470
|
+
if (!blocks.length)
|
|
19471
|
+
return;
|
|
19472
|
+
const header = "these skills are pinned and always active \u2014 follow them as trusted local instructions within the user's current request and higher-priority policy. do not call skill_load for them again.";
|
|
19473
|
+
return compactText([header, ...blocks].join(`
|
|
19474
|
+
|
|
19475
|
+
`), maxChars);
|
|
19476
|
+
}
|
|
19426
19477
|
function renderSkillCatalog(workspace, maxChars = 8000) {
|
|
19427
19478
|
const skills = listSkills(workspace);
|
|
19428
19479
|
if (!skills.length || maxChars < 80)
|
|
@@ -22068,6 +22119,28 @@ function loadLanes(workspace) {
|
|
|
22068
22119
|
function resolveLane(workspace, id2) {
|
|
22069
22120
|
return loadLanes(workspace).find((lane) => lane.id === id2);
|
|
22070
22121
|
}
|
|
22122
|
+
function laneWriteTarget(workspace) {
|
|
22123
|
+
return laneConfigPaths(workspace)[0];
|
|
22124
|
+
}
|
|
22125
|
+
function readLaneFile(path) {
|
|
22126
|
+
if (!existsSync11(path))
|
|
22127
|
+
return [];
|
|
22128
|
+
try {
|
|
22129
|
+
const parsed = JSON.parse(readBoundedFileTextSync(path, LANE_CONFIG_MAX_BYTES, "agent lane config"));
|
|
22130
|
+
if (!Array.isArray(parsed))
|
|
22131
|
+
return [];
|
|
22132
|
+
return parsed.flatMap((entry) => {
|
|
22133
|
+
const lane = normalizeLane(entry);
|
|
22134
|
+
return lane ? [lane] : [];
|
|
22135
|
+
});
|
|
22136
|
+
} catch {
|
|
22137
|
+
return [];
|
|
22138
|
+
}
|
|
22139
|
+
}
|
|
22140
|
+
function writeLaneFile(path, lanes) {
|
|
22141
|
+
atomicWriteFile(path, `${JSON.stringify(lanes, null, 2)}
|
|
22142
|
+
`, 384);
|
|
22143
|
+
}
|
|
22071
22144
|
function normalizeLane(value) {
|
|
22072
22145
|
if (!value || typeof value !== "object")
|
|
22073
22146
|
return;
|
|
@@ -22095,32 +22168,15 @@ var LANE_CONFIG_MAX_BYTES, BUILTIN_LANES;
|
|
|
22095
22168
|
var init_lanes = __esm(() => {
|
|
22096
22169
|
init_global_config();
|
|
22097
22170
|
init_file_read();
|
|
22171
|
+
init_atomic_file();
|
|
22098
22172
|
LANE_CONFIG_MAX_BYTES = 2 * 1024 * 1024;
|
|
22099
22173
|
BUILTIN_LANES = [{
|
|
22100
|
-
id: "explore",
|
|
22101
|
-
description: "read-only workspace exploration and codebase analysis",
|
|
22102
|
-
prompt: "Explore the workspace without modifying it. Return only the evidence, file references, conclusions, and unresolved questions needed by the parent.",
|
|
22103
|
-
tools: ["file_list", "file_search", "file_read", "git_status", "git_diff", "code_diagnostics", "output_read", "agent_manage"]
|
|
22104
|
-
}, {
|
|
22105
22174
|
id: "recon",
|
|
22106
|
-
description: "
|
|
22107
|
-
prompt: "
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
|
|
22111
|
-
description: "web application exploration and verification",
|
|
22112
|
-
prompt: "Audit only the delegated web scope. Use browser, HTTP, and shell capabilities as appropriate, preserve exact evidence, and return proven findings separately from uncertainty.",
|
|
22113
|
-
tools: ["browser_manage", "mail_manage", "http_request", "service_probe", "tls_inspect", "url_discover", "web_crawl", "vulnerability_scan", "vulnerability_lookup", "web_directory", "kali_search", "command_run", "command_input", "campaign_manage", "knowledge_manage", "command_poll", "command_stop", "output_read", "agent_manage"]
|
|
22114
|
-
}, {
|
|
22115
|
-
id: "code",
|
|
22116
|
-
description: "isolated software implementation, debugging, and review",
|
|
22117
|
-
prompt: "Handle only the delegated code task. Inspect before editing, preserve unrelated changes, make the smallest coherent patch, and return changed files, validation, and residual risk.",
|
|
22118
|
-
tools: ["file_list", "file_search", "file_read", "file_write", "file_replace", "file_patch", "git_status", "git_diff", "code_diagnostics", "script_write", "command_run", "command_input", "task_manage", "output_read", "agent_manage"]
|
|
22119
|
-
}, {
|
|
22120
|
-
id: "verify",
|
|
22121
|
-
description: "independent verification of evidence and candidate findings",
|
|
22122
|
-
prompt: "Independently verify only the delegated claim. Establish a baseline, run the smallest discriminating test, save evidence, and return proven, disproven, or inconclusive with exact reasoning.",
|
|
22123
|
-
tools: ["browser_manage", "http_request", "service_probe", "tls_inspect", "vulnerability_scan", "vulnerability_lookup", "command_run", "command_input", "campaign_manage", "finding_manage", "knowledge_manage", "output_read", "agent_manage"]
|
|
22175
|
+
description: "basic attack-surface reconnaissance: subdomains, dns, live probing, and crawling",
|
|
22176
|
+
prompt: ["You are a focused reconnaissance subagent. Map only the delegated target's attack surface using passive and light-active discovery: subdomain enumeration, DNS records, live HTTP/TLS probing, content and URL discovery, and crawling.", "Scope: discovery only. Do NOT exploit, brute-force, run broad port or vulnerability scanners, or perform intrusive testing \u2014 those belong to other lanes. Prefer the typed discovery tools; use shell only to run a recon CLI when no typed tool covers the need.", "Deduplicate assets, preserve exact evidence, and record the source and confidence of each item. Return a structured inventory: subdomains/hosts, resolved DNS, live services with status code and detected technology, discovered URLs and paths, and TLS facts \u2014 separating confirmed from uncertain. End with coverage gaps and the highest-value next recon steps for the parent."].join(`
|
|
22177
|
+
|
|
22178
|
+
`),
|
|
22179
|
+
tools: ["asset_subdomains", "dns_resolve", "service_probe", "tls_inspect", "url_discover", "web_crawl", "web_directory", "kali_search", "command_run", "command_input", "command_poll", "command_stop", "campaign_manage", "knowledge_manage", "output_read", "agent_manage"]
|
|
22124
22180
|
}];
|
|
22125
22181
|
});
|
|
22126
22182
|
|
|
@@ -30670,7 +30726,7 @@ var init_lifecycle2 = __esm(() => {
|
|
|
30670
30726
|
},
|
|
30671
30727
|
lane: {
|
|
30672
30728
|
type: "string",
|
|
30673
|
-
description: "capability profile
|
|
30729
|
+
description: "capability profile from the available subagent lanes (for example recon for basic attack-surface discovery), or an explicitly configured specialist lane; omit to inherit the full parent scope"
|
|
30674
30730
|
},
|
|
30675
30731
|
tools: {
|
|
30676
30732
|
type: "array",
|
|
@@ -31760,6 +31816,11 @@ var init_catalog = __esm(() => {
|
|
|
31760
31816
|
function getToolRegistry() {
|
|
31761
31817
|
return builtinRegistry;
|
|
31762
31818
|
}
|
|
31819
|
+
function listTools() {
|
|
31820
|
+
const tools = [...builtinRegistry.list().map(toolDefinition), ...listMcpTools()];
|
|
31821
|
+
assertUniqueTools(tools);
|
|
31822
|
+
return tools;
|
|
31823
|
+
}
|
|
31763
31824
|
function listToolsForSession(session) {
|
|
31764
31825
|
const tools = [...builtinRegistry.list().map(toolDefinition), ...listMcpTools(session)];
|
|
31765
31826
|
assertUniqueTools(tools);
|
|
@@ -33598,13 +33659,13 @@ async function resolveModelSelection(workspace, selection) {
|
|
|
33598
33659
|
if (selection) {
|
|
33599
33660
|
const selected = (await buildModelCatalog(workspace)).models.find((model) => model.id === selection);
|
|
33600
33661
|
if (selected)
|
|
33601
|
-
return withSavedModelLimits(modelChoiceToResolved(selected), selection, workspace);
|
|
33662
|
+
return withModelsDevLimits(withSavedModelLimits(modelChoiceToResolved(selected), selection, workspace), selection, workspace);
|
|
33602
33663
|
const profileResolved = await resolveProfileAsync(loadModelProfiles(workspace), selection);
|
|
33603
33664
|
if (profileResolved?.model)
|
|
33604
|
-
return withSavedModelLimits(profileResolved, selection, workspace);
|
|
33605
|
-
return withSavedModelLimits(ensureConcrete(resolveModel({
|
|
33665
|
+
return withModelsDevLimits(withSavedModelLimits(profileResolved, selection, workspace), selection, workspace);
|
|
33666
|
+
return withModelsDevLimits(withSavedModelLimits(ensureConcrete(resolveModel({
|
|
33606
33667
|
model: selection
|
|
33607
|
-
})), selection, workspace);
|
|
33668
|
+
})), selection, workspace), selection, workspace);
|
|
33608
33669
|
}
|
|
33609
33670
|
return resolveDefaultCatalogModel(workspace);
|
|
33610
33671
|
}
|
|
@@ -33928,6 +33989,22 @@ async function lookupModelsDevLimits(model, providerHint, baseUrlHint) {
|
|
|
33928
33989
|
} : {}
|
|
33929
33990
|
};
|
|
33930
33991
|
}
|
|
33992
|
+
async function withModelsDevLimits(resolved, selection, workspace) {
|
|
33993
|
+
if (resolved.contextWindow)
|
|
33994
|
+
return resolved;
|
|
33995
|
+
const profile = resolveProfile(loadModelProfiles(workspace), selection);
|
|
33996
|
+
const lookupModel = resolved.model ?? profile?.model ?? selection;
|
|
33997
|
+
const fetched = await lookupModelsDevLimits(lookupModel, profile ? selection : undefined, resolved.baseUrl ?? profile?.baseUrl);
|
|
33998
|
+
if (!fetched?.contextWindow)
|
|
33999
|
+
return resolved;
|
|
34000
|
+
return {
|
|
34001
|
+
...resolved,
|
|
34002
|
+
contextWindow: fetched.contextWindow,
|
|
34003
|
+
...resolved.maxOutputTokens ? {} : fetched.maxOutputTokens ? {
|
|
34004
|
+
maxOutputTokens: fetched.maxOutputTokens
|
|
34005
|
+
} : {}
|
|
34006
|
+
};
|
|
34007
|
+
}
|
|
33931
34008
|
function withSavedModelLimits(resolved, selection, workspace) {
|
|
33932
34009
|
const saved = loadConfig(workspace).modelLimits?.[selection];
|
|
33933
34010
|
if (!saved)
|
|
@@ -34198,7 +34275,7 @@ function buildSystemPromptBlocks(input) {
|
|
|
34198
34275
|
`)
|
|
34199
34276
|
}, {
|
|
34200
34277
|
title: "State and Delegation",
|
|
34201
|
-
body: ["Treat active jobs as live state: reuse or poll relevant work instead of duplicating it. Completion is delivered automatically.", "Keep the current session name concise and specific. Farai derives an initial name from the first substantive user request; call session_manage once when that fallback is vague or the durable goal materially changes. Do not rename a session for greetings, temporary substeps, or routine follow-ups.", 'Use agent_manage
|
|
34278
|
+
body: ["Treat active jobs as live state: reuse or poll relevant work instead of duplicating it. Completion is delivered automatically.", "Keep the current session name concise and specific. Farai derives an initial name from the first substantive user request; call session_manage once when that fallback is vague or the durable goal materially changes. Do not rename a session for greetings, temporary substeps, or routine follow-ups.", "Work as an orchestrator: delegate whole units of work to subagents and keep this thread coordinating. Judge by the size of the work. A self-contained objective that spans several steps or tools, benefits from its own context, can run in parallel with other work, or needs a specialist role \u2014 for example map and probe an attack surface, test authorization across an app, or review and patch a module \u2014 should be delegated to a subagent (a matching lane from Available Subagent Lanes when one fits, otherwise a plain child that inherits scope). Do NOT spawn a subagent just to run one tool: call that tool directly, and if it is slow, run it in the background and poll rather than wrapping it in a child. Answer trivial requests directly. When you do delegate, keep this thread planning, splitting non-overlapping work, dispatching workers (in parallel when independent), monitoring, and synthesizing results into the user's answer.", 'Use agent_manage for work that benefits from independent context, parallel I/O, persistent browser state, specialist tools, or independent verification. Use operation=spawn to start a child, list or wait to inspect it, message to steer active work, followup to continue an idle child, and interrupt or close for lifecycle cleanup. Put operation-specific fields inside args. Children inherit the parent model by default; omit model unless an explicit model override is required. Pick a lane from the Available Subagent Lanes list (each has a role and tool scope); do not assume only the builtin lanes exist. Prefer detached delegation for work you can run in the background or in parallel: pass args.mode="detached" (never detached=true) so the child runs without blocking you and its result is delivered back automatically on completion \u2014 fan out several non-overlapping detached children and keep working instead of idling on one. Detached children must be non-editing and independently useful; use attached (blocking) mode when you need the result before the next step or when the child edits the shared workspace. While children run, use operation=list or wait to check progress, message to steer an active child, and followup to give an idle child more work. Give parallel workers non-overlapping ownership, and keep synthesis and the user-facing answer in the parent.', "Campaigns are model-decided: for multi-step authorized work needing durable evidence, waves, coordination, verification, or reporting, call campaign_manage with the relevant operation; avoid it for one-off tasks. While active, use campaign_manage operations, define only the requirements that matter for this objective, and checkpoint each wave; the runtime handles leases, recovery, and final validation."].join(`
|
|
34202
34279
|
`)
|
|
34203
34280
|
}, {
|
|
34204
34281
|
title: "Trust Boundary",
|
|
@@ -36440,12 +36517,13 @@ function actionsFromMessage(message) {
|
|
|
36440
36517
|
} : {}
|
|
36441
36518
|
});
|
|
36442
36519
|
} catch (error) {
|
|
36520
|
+
const baseError = error instanceof Error ? error.message : String(error);
|
|
36443
36521
|
actions.push({
|
|
36444
36522
|
kind: "tool_parse_error",
|
|
36445
36523
|
tool: name,
|
|
36446
36524
|
toolCallId: call2.id ?? name,
|
|
36447
36525
|
rawArguments: raw,
|
|
36448
|
-
error:
|
|
36526
|
+
error: isProviderIncompleteFinishReason(finishReason) ? `${baseError} (the provider truncated the response before the tool arguments finished, finish_reason=${finishReason ?? "unknown"}; retry or switch model)` : baseError
|
|
36449
36527
|
});
|
|
36450
36528
|
}
|
|
36451
36529
|
}
|
|
@@ -36973,6 +37051,10 @@ function fitToolResultText(text2, maxBytes) {
|
|
|
36973
37051
|
var init_history = () => {};
|
|
36974
37052
|
|
|
36975
37053
|
// src/agent-core/history-projection.ts
|
|
37054
|
+
function isLocalCommandInput(text2) {
|
|
37055
|
+
const trimmed = text2.trimStart();
|
|
37056
|
+
return trimmed.startsWith("/") || trimmed.startsWith("!");
|
|
37057
|
+
}
|
|
36976
37058
|
function projectConversationHistory(messages, options = {}) {
|
|
36977
37059
|
const overlay = options.overlay;
|
|
36978
37060
|
const providerToolCallIds = new Map;
|
|
@@ -37012,7 +37094,7 @@ function projectConversationHistory(messages, options = {}) {
|
|
|
37012
37094
|
continue;
|
|
37013
37095
|
}
|
|
37014
37096
|
const text2 = part.payload.text;
|
|
37015
|
-
if (typeof text2 === "string" && text2)
|
|
37097
|
+
if (typeof text2 === "string" && text2 && !isLocalCommandInput(text2))
|
|
37016
37098
|
entries.push({
|
|
37017
37099
|
role: "user",
|
|
37018
37100
|
text: text2,
|
|
@@ -37316,6 +37398,7 @@ class ContextManager {
|
|
|
37316
37398
|
for (const nodeId of chunk.coveredNodeIds)
|
|
37317
37399
|
covered.add(nodeId);
|
|
37318
37400
|
const activeJobs = new Set(activeBackgroundJobs(this.store.listToolCalls(session.id, 200)).map((job) => job.toolCallId));
|
|
37401
|
+
const windowTokens = resolveContextWindow(planner.contextWindow);
|
|
37319
37402
|
for (const policy of this.lanes) {
|
|
37320
37403
|
if (signal.aborted)
|
|
37321
37404
|
return;
|
|
@@ -37336,7 +37419,7 @@ class ContextManager {
|
|
|
37336
37419
|
} : {}
|
|
37337
37420
|
});
|
|
37338
37421
|
}
|
|
37339
|
-
for (const plan of policy.planChunks(nodes)) {
|
|
37422
|
+
for (const plan of policy.planChunks(nodes, windowTokens)) {
|
|
37340
37423
|
if (signal.aborted)
|
|
37341
37424
|
return;
|
|
37342
37425
|
const chunkNodes = nodes.filter((node) => plan.coveredNodeIds.includes(node.nodeId));
|
|
@@ -37499,27 +37582,31 @@ var init_context_manager2 = __esm(() => {
|
|
|
37499
37582
|
init_history_projection();
|
|
37500
37583
|
init_background();
|
|
37501
37584
|
init_summary_runner();
|
|
37585
|
+
init_model_registry();
|
|
37502
37586
|
});
|
|
37503
37587
|
|
|
37504
37588
|
// src/agent-context/lanes.ts
|
|
37505
37589
|
class SummarizeLanePolicy {
|
|
37506
37590
|
constructor(options = {}) {
|
|
37507
37591
|
this.lane = options.lane ?? "tool";
|
|
37508
|
-
this.chunkSize = Math.max(2, options.chunkSize ??
|
|
37509
|
-
this.triggerUncovered = Math.max(this.chunkSize, options.triggerUncovered ?? 30);
|
|
37592
|
+
this.chunkSize = Math.max(2, options.chunkSize ?? 8);
|
|
37510
37593
|
this.protectedTail = Math.max(0, options.protectedTail ?? 10);
|
|
37594
|
+
this.triggerFraction = Math.max(0, options.triggerFraction ?? 0.15);
|
|
37595
|
+
this.triggerTokensFloor = Math.max(0, options.triggerTokensFloor ?? 25000);
|
|
37511
37596
|
}
|
|
37512
37597
|
classify(entry) {
|
|
37513
37598
|
return entry.role === "tool";
|
|
37514
37599
|
}
|
|
37515
|
-
planChunks(nodes) {
|
|
37600
|
+
planChunks(nodes, windowTokens) {
|
|
37516
37601
|
const protectedFrom = Math.max(0, nodes.length - this.protectedTail);
|
|
37517
37602
|
const eligible = nodes.filter((node, index) => !node.covered && node.settled && index < protectedFrom);
|
|
37518
|
-
if (eligible.length < this.
|
|
37603
|
+
if (eligible.length < this.chunkSize)
|
|
37519
37604
|
return [];
|
|
37520
|
-
const
|
|
37521
|
-
|
|
37605
|
+
const eligibleTokens = eligible.reduce((total, node) => total + Math.ceil(node.bytes / 4), 0);
|
|
37606
|
+
const threshold = Math.max(this.triggerTokensFloor, Math.round(windowTokens * this.triggerFraction));
|
|
37607
|
+
if (eligibleTokens < threshold)
|
|
37522
37608
|
return [];
|
|
37609
|
+
const batch = eligible.slice(0, this.chunkSize);
|
|
37523
37610
|
return [{
|
|
37524
37611
|
lane: this.lane,
|
|
37525
37612
|
coveredNodeIds: batch.map((node) => node.nodeId),
|
|
@@ -39096,6 +39183,35 @@ Phase: ${session.phase}`,
|
|
|
39096
39183
|
priority: 95,
|
|
39097
39184
|
relevance: 1
|
|
39098
39185
|
}));
|
|
39186
|
+
const pinnedNames = this.skillsEnabled && canLoadSkills ? loadConfig(workspace).pinnedSkills ?? [] : [];
|
|
39187
|
+
const pinnedSkills = pinnedNames.length ? renderPinnedSkills(workspace, pinnedNames) : undefined;
|
|
39188
|
+
if (pinnedSkills)
|
|
39189
|
+
candidates.push(candidate({
|
|
39190
|
+
id: "pinned-skills",
|
|
39191
|
+
class: "instructions",
|
|
39192
|
+
title: "Pinned Skills",
|
|
39193
|
+
source: "agent-skills registry (pinned)",
|
|
39194
|
+
content: pinnedSkills,
|
|
39195
|
+
mandatory: true,
|
|
39196
|
+
stable: true,
|
|
39197
|
+
priority: 98,
|
|
39198
|
+
relevance: 1
|
|
39199
|
+
}));
|
|
39200
|
+
const canDelegate = !session.toolScope?.length || session.toolScope.some((name) => canonicalToolName(name) === "agent_manage");
|
|
39201
|
+
const lanes = canDelegate ? loadLanes(workspace) : [];
|
|
39202
|
+
if (lanes.length)
|
|
39203
|
+
candidates.push(candidate({
|
|
39204
|
+
id: "subagent-lanes",
|
|
39205
|
+
class: "capabilities",
|
|
39206
|
+
title: "Available Subagent Lanes",
|
|
39207
|
+
source: "subagent role registry",
|
|
39208
|
+
content: ["Delegate whole units of work to subagents (agent_manage): a multi-step objective, specialist work, or something that can run in parallel \u2014 pick the matching lane below when one fits, otherwise a plain child. Do not spawn a child just to run one tool (run a single slow tool in the background instead). Keep this thread as the orchestrator that plans, dispatches non-overlapping work in parallel, and owns synthesis. Lanes carry a role prompt and tool scope.", "Available lanes:", ...lanes.map((lane) => `- ${lane.id}: ${lane.description ?? "custom lane"}`)].join(`
|
|
39209
|
+
`),
|
|
39210
|
+
mandatory: false,
|
|
39211
|
+
stable: true,
|
|
39212
|
+
priority: 94,
|
|
39213
|
+
relevance: 1
|
|
39214
|
+
}));
|
|
39099
39215
|
if (isCodingTask(session, query)) {
|
|
39100
39216
|
const outline = buildWorkspaceOutline(workspace, query, recentPaths, this.contextBuilder);
|
|
39101
39217
|
if (outline)
|
|
@@ -39475,6 +39591,7 @@ var EPHEMERAL_CONTEXT_MAX_BYTES, WORKING_FILES_COUNT = 6, WORKING_FILE_MAX_BYTES
|
|
|
39475
39591
|
var init_context_engine = __esm(() => {
|
|
39476
39592
|
init_tool_names();
|
|
39477
39593
|
init_registry2();
|
|
39594
|
+
init_config();
|
|
39478
39595
|
init_background();
|
|
39479
39596
|
init_summary_runner();
|
|
39480
39597
|
init_provider();
|
|
@@ -39483,6 +39600,7 @@ var init_context_engine = __esm(() => {
|
|
|
39483
39600
|
init_capability_admission();
|
|
39484
39601
|
init_kali_command_catalog();
|
|
39485
39602
|
init_kali();
|
|
39603
|
+
init_lanes();
|
|
39486
39604
|
init_cvss31_guidance();
|
|
39487
39605
|
EPHEMERAL_CONTEXT_MAX_BYTES = 12 * 1024;
|
|
39488
39606
|
WORKING_FILE_MAX_BYTES = 12 * 1024;
|
|
@@ -39490,7 +39608,7 @@ var init_context_engine = __esm(() => {
|
|
|
39490
39608
|
});
|
|
39491
39609
|
|
|
39492
39610
|
// src/agent-core/context-report.ts
|
|
39493
|
-
function buildContextReport(manifest, model, columns = 20,
|
|
39611
|
+
function buildContextReport(manifest, model, columns = 20, cellTokens = CELL_TOKENS) {
|
|
39494
39612
|
const window = Math.max(1, manifest.contextWindow);
|
|
39495
39613
|
const used = Math.min(window, Math.max(0, Math.round(manifest.estimatedTokens)));
|
|
39496
39614
|
const slices = [];
|
|
@@ -39505,7 +39623,7 @@ function buildContextReport(manifest, model, columns = 20, rows = 5) {
|
|
|
39505
39623
|
});
|
|
39506
39624
|
}
|
|
39507
39625
|
const free = Math.max(0, window - used);
|
|
39508
|
-
const totalCells = Math.max(1,
|
|
39626
|
+
const totalCells = Math.max(1, Math.min(MAX_CELLS, Math.round(window / Math.max(1, cellTokens))));
|
|
39509
39627
|
const usedCells = Math.min(totalCells, Math.round(used / window * totalCells));
|
|
39510
39628
|
const grid = [];
|
|
39511
39629
|
for (const slice of slices) {
|
|
@@ -39528,7 +39646,7 @@ function buildContextReport(manifest, model, columns = 20, rows = 5) {
|
|
|
39528
39646
|
columns
|
|
39529
39647
|
};
|
|
39530
39648
|
}
|
|
39531
|
-
var CATEGORIES;
|
|
39649
|
+
var CATEGORIES, CELL_TOKENS = 3000, MAX_CELLS = 1000;
|
|
39532
39650
|
var init_context_report = __esm(() => {
|
|
39533
39651
|
CATEGORIES = [{
|
|
39534
39652
|
key: "kernel",
|
|
@@ -46316,7 +46434,7 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
46316
46434
|
return text2;
|
|
46317
46435
|
}
|
|
46318
46436
|
if (command === "/context") {
|
|
46319
|
-
const report = buildContextReport(this.inspectContext(session), session.model ?? "");
|
|
46437
|
+
const report = buildContextReport(await this.inspectContext(session), session.model ?? "");
|
|
46320
46438
|
this.store.addPart({
|
|
46321
46439
|
sessionId: session.id,
|
|
46322
46440
|
turnId: turn.id,
|
|
@@ -46528,15 +46646,17 @@ This completion is already terminal and was delivered automatically. Do not call
|
|
|
46528
46646
|
}
|
|
46529
46647
|
return this.toolOperationDrain;
|
|
46530
46648
|
}
|
|
46531
|
-
inspectContext(session, hypotheticalInput) {
|
|
46649
|
+
async inspectContext(session, hypotheticalInput) {
|
|
46650
|
+
const current = this.store.loadSession(session.id);
|
|
46651
|
+
const planner = this.planner ?? await createPlannerForSessionAsync(current, this.workspace);
|
|
46532
46652
|
return this.assembleContext({
|
|
46533
|
-
session:
|
|
46653
|
+
session: current,
|
|
46534
46654
|
...hypotheticalInput?.trim() ? {
|
|
46535
46655
|
userText: hypotheticalInput.trim()
|
|
46536
46656
|
} : {},
|
|
46537
|
-
availableTools: listToolsForSession(
|
|
46538
|
-
contextWindow: resolveContextWindow(
|
|
46539
|
-
maxOutputTokens: resolveMaxOutputTokens(
|
|
46657
|
+
availableTools: listToolsForSession(current),
|
|
46658
|
+
contextWindow: resolveContextWindow(planner.contextWindow),
|
|
46659
|
+
maxOutputTokens: resolveMaxOutputTokens(planner.maxOutputTokens),
|
|
46540
46660
|
...this.contextBudgetInput()
|
|
46541
46661
|
}).manifest;
|
|
46542
46662
|
}
|
|
@@ -50844,6 +50964,66 @@ var init_model_provider_management = __esm(() => {
|
|
|
50844
50964
|
MODEL_PROBE_MAX_BYTES = 8 * 1024 * 1024;
|
|
50845
50965
|
});
|
|
50846
50966
|
|
|
50967
|
+
// src/agent-core/subagents/lane-management.ts
|
|
50968
|
+
function listLanes(workspace) {
|
|
50969
|
+
const paths = laneConfigPaths(workspace);
|
|
50970
|
+
const writeTarget = laneWriteTarget(workspace);
|
|
50971
|
+
const globalIds = new Set(readLaneFile(writeTarget).map((lane) => lane.id));
|
|
50972
|
+
const overrideIds = new Set(paths.filter((path) => path !== writeTarget).flatMap((path) => readLaneFile(path).map((lane) => lane.id)));
|
|
50973
|
+
const builtinIds = new Set(BUILTIN_LANES.map((lane) => lane.id));
|
|
50974
|
+
return loadLanes(workspace).map((lane) => {
|
|
50975
|
+
const source = overrideIds.has(lane.id) ? "workspace" : globalIds.has(lane.id) ? "global" : builtinIds.has(lane.id) ? "builtin" : "global";
|
|
50976
|
+
return {
|
|
50977
|
+
...lane,
|
|
50978
|
+
source,
|
|
50979
|
+
editable: source !== "workspace"
|
|
50980
|
+
};
|
|
50981
|
+
});
|
|
50982
|
+
}
|
|
50983
|
+
function saveLane(workspace, input) {
|
|
50984
|
+
const id2 = input.id.trim();
|
|
50985
|
+
if (!LANE_ID.test(id2))
|
|
50986
|
+
throw new Error("lane id must match ^[a-z0-9][a-z0-9_-]*$");
|
|
50987
|
+
const tools = input.tools ? [...new Set(input.tools.map((tool) => tool.trim()).filter(Boolean))] : undefined;
|
|
50988
|
+
if (input.tools && !tools?.length)
|
|
50989
|
+
throw new Error("tools must contain at least one non-empty tool name");
|
|
50990
|
+
const definition = {
|
|
50991
|
+
id: id2,
|
|
50992
|
+
...input.description?.trim() ? {
|
|
50993
|
+
description: input.description.trim()
|
|
50994
|
+
} : {},
|
|
50995
|
+
...input.prompt?.trim() ? {
|
|
50996
|
+
prompt: input.prompt.trim()
|
|
50997
|
+
} : {},
|
|
50998
|
+
...tools?.length ? {
|
|
50999
|
+
tools
|
|
51000
|
+
} : {},
|
|
51001
|
+
...input.model?.trim() ? {
|
|
51002
|
+
model: input.model.trim()
|
|
51003
|
+
} : {}
|
|
51004
|
+
};
|
|
51005
|
+
const target = laneWriteTarget(workspace);
|
|
51006
|
+
const current = readLaneFile(target).filter((lane) => lane.id !== id2);
|
|
51007
|
+
writeLaneFile(target, [...current, definition]);
|
|
51008
|
+
return {
|
|
51009
|
+
...definition,
|
|
51010
|
+
source: "global",
|
|
51011
|
+
editable: true
|
|
51012
|
+
};
|
|
51013
|
+
}
|
|
51014
|
+
function removeLane(workspace, id2) {
|
|
51015
|
+
const target = laneWriteTarget(workspace);
|
|
51016
|
+
const current = readLaneFile(target);
|
|
51017
|
+
if (!current.some((lane) => lane.id === id2))
|
|
51018
|
+
throw new Error(`no custom lane to remove: ${id2}`);
|
|
51019
|
+
writeLaneFile(target, current.filter((lane) => lane.id !== id2));
|
|
51020
|
+
}
|
|
51021
|
+
var LANE_ID;
|
|
51022
|
+
var init_lane_management = __esm(() => {
|
|
51023
|
+
init_lanes();
|
|
51024
|
+
LANE_ID = /^[a-z0-9][a-z0-9_-]*$/;
|
|
51025
|
+
});
|
|
51026
|
+
|
|
50847
51027
|
// src/agent-email/oauth-providers.ts
|
|
50848
51028
|
function emailOAuthProvider(provider) {
|
|
50849
51029
|
return EMAIL_OAUTH_PROVIDERS[provider];
|
|
@@ -51519,6 +51699,20 @@ function createRuntimePort(runtime, options = {}) {
|
|
|
51519
51699
|
statuses: listMcpServerStatuses(activeSessionId)
|
|
51520
51700
|
};
|
|
51521
51701
|
},
|
|
51702
|
+
async listLanes() {
|
|
51703
|
+
return listLanes(runtime.workspace);
|
|
51704
|
+
},
|
|
51705
|
+
async listToolNames() {
|
|
51706
|
+
return [...new Set(listTools().map((tool) => tool.name))].sort();
|
|
51707
|
+
},
|
|
51708
|
+
async saveLane(input) {
|
|
51709
|
+
saveLane(runtime.workspace, input);
|
|
51710
|
+
return listLanes(runtime.workspace);
|
|
51711
|
+
},
|
|
51712
|
+
async removeLane(id2) {
|
|
51713
|
+
removeLane(runtime.workspace, id2);
|
|
51714
|
+
return listLanes(runtime.workspace);
|
|
51715
|
+
},
|
|
51522
51716
|
async setMcpServerEnabled(serverID, enabled) {
|
|
51523
51717
|
await setMcpServerEnabled(runtime.workspace, serverID, enabled);
|
|
51524
51718
|
if (activeSessionId)
|
|
@@ -51590,7 +51784,7 @@ function createRuntimePort(runtime, options = {}) {
|
|
|
51590
51784
|
return runtime.takeBackQueuedUserInput(sessionId);
|
|
51591
51785
|
},
|
|
51592
51786
|
async inspectContext(sessionId, hypotheticalInput) {
|
|
51593
|
-
return runtime.inspectContext(runtime.loadSession(sessionId), hypotheticalInput);
|
|
51787
|
+
return await runtime.inspectContext(runtime.loadSession(sessionId), hypotheticalInput);
|
|
51594
51788
|
},
|
|
51595
51789
|
steer(sessionId, input) {
|
|
51596
51790
|
return runtime.injectUserInput(sessionId, input);
|
|
@@ -51943,6 +52137,8 @@ var init_runtime_port = __esm(() => {
|
|
|
51943
52137
|
init_model_registry();
|
|
51944
52138
|
init_context_manager();
|
|
51945
52139
|
init_mcp_server_management();
|
|
52140
|
+
init_lane_management();
|
|
52141
|
+
init_registry4();
|
|
51946
52142
|
init_accounts();
|
|
51947
52143
|
init_oauth_providers();
|
|
51948
52144
|
init_oauth();
|
|
@@ -52076,6 +52272,59 @@ var init_model_provider_state = __esm(() => {
|
|
|
52076
52272
|
PROTOCOL_ORDER = ["auto", "openai-chat", "anthropic-messages"];
|
|
52077
52273
|
});
|
|
52078
52274
|
|
|
52275
|
+
// src/agent-tui/lane-state.ts
|
|
52276
|
+
function createLaneWizard(lane) {
|
|
52277
|
+
if (!lane) {
|
|
52278
|
+
return {
|
|
52279
|
+
mode: "add",
|
|
52280
|
+
field: "id",
|
|
52281
|
+
id: "",
|
|
52282
|
+
description: "",
|
|
52283
|
+
prompt: "",
|
|
52284
|
+
tools: [],
|
|
52285
|
+
toolFilter: "",
|
|
52286
|
+
toolCursor: 0,
|
|
52287
|
+
model: "",
|
|
52288
|
+
busy: false,
|
|
52289
|
+
error: undefined
|
|
52290
|
+
};
|
|
52291
|
+
}
|
|
52292
|
+
return {
|
|
52293
|
+
mode: "edit",
|
|
52294
|
+
field: "description",
|
|
52295
|
+
id: lane.id,
|
|
52296
|
+
originalID: lane.id,
|
|
52297
|
+
description: lane.description ?? "",
|
|
52298
|
+
prompt: lane.prompt ?? "",
|
|
52299
|
+
tools: [...lane.tools ?? []],
|
|
52300
|
+
toolFilter: "",
|
|
52301
|
+
toolCursor: 0,
|
|
52302
|
+
model: lane.model ?? "",
|
|
52303
|
+
busy: false,
|
|
52304
|
+
error: undefined
|
|
52305
|
+
};
|
|
52306
|
+
}
|
|
52307
|
+
function laneWizardFieldMove(field, delta) {
|
|
52308
|
+
const index = FIELD_ORDER2.indexOf(field);
|
|
52309
|
+
return FIELD_ORDER2[Math.max(0, Math.min(FIELD_ORDER2.length - 1, index + delta))] ?? field;
|
|
52310
|
+
}
|
|
52311
|
+
function laneWizardStep(field) {
|
|
52312
|
+
return FIELD_ORDER2.indexOf(field) + 1;
|
|
52313
|
+
}
|
|
52314
|
+
function laneWizardStepCount() {
|
|
52315
|
+
return FIELD_ORDER2.length;
|
|
52316
|
+
}
|
|
52317
|
+
function filteredToolNames(all, filter) {
|
|
52318
|
+
const needle = filter.trim().toLowerCase();
|
|
52319
|
+
if (!needle)
|
|
52320
|
+
return all;
|
|
52321
|
+
return all.filter((name) => name.toLowerCase().includes(needle));
|
|
52322
|
+
}
|
|
52323
|
+
var FIELD_ORDER2;
|
|
52324
|
+
var init_lane_state = __esm(() => {
|
|
52325
|
+
FIELD_ORDER2 = ["id", "description", "prompt", "tools", "model", "review"];
|
|
52326
|
+
});
|
|
52327
|
+
|
|
52079
52328
|
// src/agent-tui/mcp-server-state.ts
|
|
52080
52329
|
function createMcpServerWizard(server) {
|
|
52081
52330
|
if (!server) {
|
|
@@ -52650,6 +52899,10 @@ function initialStore(workspace) {
|
|
|
52650
52899
|
},
|
|
52651
52900
|
sessionStats: {},
|
|
52652
52901
|
agentThreads: [],
|
|
52902
|
+
lanes: [],
|
|
52903
|
+
toolNames: [],
|
|
52904
|
+
laneWizard: undefined,
|
|
52905
|
+
laneRemoval: undefined,
|
|
52653
52906
|
lastError: undefined,
|
|
52654
52907
|
requestUserInput: undefined,
|
|
52655
52908
|
updateNotice: undefined
|
|
@@ -53408,6 +53661,56 @@ function createActions(store, setStore) {
|
|
|
53408
53661
|
key: "id"
|
|
53409
53662
|
}));
|
|
53410
53663
|
},
|
|
53664
|
+
lanesSet(lanes) {
|
|
53665
|
+
setStore("ui", "lanes", reconcile(lanes, {
|
|
53666
|
+
key: "id"
|
|
53667
|
+
}));
|
|
53668
|
+
},
|
|
53669
|
+
toolNamesSet(names) {
|
|
53670
|
+
setStore("ui", "toolNames", names);
|
|
53671
|
+
},
|
|
53672
|
+
laneWizardOpen(lane) {
|
|
53673
|
+
setStore(produce((s) => {
|
|
53674
|
+
s.ui.lastError = undefined;
|
|
53675
|
+
s.ui.laneWizard = createLaneWizard(lane);
|
|
53676
|
+
}));
|
|
53677
|
+
},
|
|
53678
|
+
laneWizardPatch(patch) {
|
|
53679
|
+
setStore(produce((s) => {
|
|
53680
|
+
if (!s.ui.laneWizard)
|
|
53681
|
+
return;
|
|
53682
|
+
Object.assign(s.ui.laneWizard, patch);
|
|
53683
|
+
}));
|
|
53684
|
+
},
|
|
53685
|
+
laneWizardClose() {
|
|
53686
|
+
setStore(produce((s) => {
|
|
53687
|
+
s.ui.laneWizard = undefined;
|
|
53688
|
+
s.ui.lastError = undefined;
|
|
53689
|
+
}));
|
|
53690
|
+
},
|
|
53691
|
+
laneRemovalOpen(lane) {
|
|
53692
|
+
setStore(produce((s) => {
|
|
53693
|
+
s.ui.lastError = undefined;
|
|
53694
|
+
s.ui.laneRemoval = {
|
|
53695
|
+
lane,
|
|
53696
|
+
busy: false,
|
|
53697
|
+
error: undefined
|
|
53698
|
+
};
|
|
53699
|
+
}));
|
|
53700
|
+
},
|
|
53701
|
+
laneRemovalPatch(patch) {
|
|
53702
|
+
setStore(produce((s) => {
|
|
53703
|
+
if (!s.ui.laneRemoval)
|
|
53704
|
+
return;
|
|
53705
|
+
Object.assign(s.ui.laneRemoval, patch);
|
|
53706
|
+
}));
|
|
53707
|
+
},
|
|
53708
|
+
laneRemovalClose() {
|
|
53709
|
+
setStore(produce((s) => {
|
|
53710
|
+
s.ui.laneRemoval = undefined;
|
|
53711
|
+
s.ui.lastError = undefined;
|
|
53712
|
+
}));
|
|
53713
|
+
},
|
|
53411
53714
|
messageNavigationRequested(direction) {
|
|
53412
53715
|
setStore(produce((s) => {
|
|
53413
53716
|
s.ui.messageNavigation.direction = direction;
|
|
@@ -53765,6 +54068,7 @@ function defaultOverlayFrame(kind) {
|
|
|
53765
54068
|
case "evidence":
|
|
53766
54069
|
case "findings":
|
|
53767
54070
|
case "memory":
|
|
54071
|
+
case "subagents":
|
|
53768
54072
|
case "agents":
|
|
53769
54073
|
case "model":
|
|
53770
54074
|
case "mcp":
|
|
@@ -53800,6 +54104,7 @@ function isSelectorOverlayKind(kind) {
|
|
|
53800
54104
|
case "evidence":
|
|
53801
54105
|
case "findings":
|
|
53802
54106
|
case "memory":
|
|
54107
|
+
case "subagents":
|
|
53803
54108
|
case "agents":
|
|
53804
54109
|
case "model":
|
|
53805
54110
|
case "mcp":
|
|
@@ -53825,6 +54130,7 @@ var init_store3 = __esm(() => {
|
|
|
53825
54130
|
init_store2();
|
|
53826
54131
|
init_runtime_port();
|
|
53827
54132
|
init_model_provider_state();
|
|
54133
|
+
init_lane_state();
|
|
53828
54134
|
init_mcp_server_state();
|
|
53829
54135
|
init_email_account_state();
|
|
53830
54136
|
PROXY_VIEW_FILTERS = ["all", "http", "websocket"];
|
|
@@ -55009,6 +55315,8 @@ var init_tool_presentation = __esm(() => {
|
|
|
55009
55315
|
write: "writing"
|
|
55010
55316
|
};
|
|
55011
55317
|
TOOL_ACTIONS = {
|
|
55318
|
+
command_run: ["ran", "executing"],
|
|
55319
|
+
command_input: ["sent input", "sending input"],
|
|
55012
55320
|
agent_manage: ["managed agents", "managing agents"],
|
|
55013
55321
|
browser_manage: ["managed browser", "managing browser"],
|
|
55014
55322
|
callback_manage: ["managed callbacks", "managing callbacks"],
|
|
@@ -55464,6 +55772,15 @@ var init_tool_lifecycle = __esm(() => {
|
|
|
55464
55772
|
detail: "summary",
|
|
55465
55773
|
showOutcome: false,
|
|
55466
55774
|
groupItem: (args) => stringValue2(args.canonical)
|
|
55775
|
+
},
|
|
55776
|
+
command_poll: {
|
|
55777
|
+
groupKey: "background:poll",
|
|
55778
|
+
groupPast: "checked background work",
|
|
55779
|
+
groupActive: "checking background work",
|
|
55780
|
+
groupNoun: "check",
|
|
55781
|
+
groupMaxItems: 20,
|
|
55782
|
+
detail: "summary",
|
|
55783
|
+
showOutcome: false
|
|
55467
55784
|
}
|
|
55468
55785
|
};
|
|
55469
55786
|
BROWSER_TOOLS = new Set(["browser_navigate", "browser_snapshot", "browser_find", "browser_click", "browser_fill_form", "browser_type", "browser_press_key", "browser_wait_for", "browser_tabs", "browser_network_requests", "browser_network_request"]);
|
|
@@ -56726,9 +57043,7 @@ function activityLabel(rows, active) {
|
|
|
56726
57043
|
const verb = active ? presentation.groupActive ?? "running" : presentation.groupPast ?? "ran";
|
|
56727
57044
|
const [action = verb, qualifier] = verb.split(" \xB7 ", 2);
|
|
56728
57045
|
if (presentation.groupNoun) {
|
|
56729
|
-
|
|
56730
|
-
const listed = names.slice(0, 5).join(", ");
|
|
56731
|
-
return `${action} ${listed || `${count2} ${presentation.groupNoun}${count2 === 1 ? "" : "s"}`}${names.length > 5 ? `, +${names.length - 5}` : ""}`;
|
|
57046
|
+
return `${action} \xB7 ${count2}${qualifier ? ` \xB7 ${qualifier}` : ""}`;
|
|
56732
57047
|
}
|
|
56733
57048
|
return `${action} ${count2} ${presentation.noun}${count2 === 1 ? "" : "s"}${qualifier ? ` \xB7 ${qualifier}` : ""}`;
|
|
56734
57049
|
}
|
|
@@ -57789,6 +58104,19 @@ function createStoreResourceController(input) {
|
|
|
57789
58104
|
agentThreadRefreshes.clear();
|
|
57790
58105
|
containerToggles.clear();
|
|
57791
58106
|
}
|
|
58107
|
+
async function openSubagentsOverlay() {
|
|
58108
|
+
actions.overlayOpen("subagents");
|
|
58109
|
+
try {
|
|
58110
|
+
const [lanes, toolNames] = await Promise.all([port.listLanes(), port.listToolNames()]);
|
|
58111
|
+
if (store.ui.overlayStack.at(-1)?.kind === "subagents") {
|
|
58112
|
+
actions.lanesSet(lanes);
|
|
58113
|
+
actions.toolNamesSet(toolNames);
|
|
58114
|
+
}
|
|
58115
|
+
} catch (error) {
|
|
58116
|
+
if (store.ui.overlayStack.at(-1)?.kind === "subagents")
|
|
58117
|
+
actions.errorSet(error instanceof Error ? error.message : String(error));
|
|
58118
|
+
}
|
|
58119
|
+
}
|
|
57792
58120
|
return {
|
|
57793
58121
|
refreshSessionMcp,
|
|
57794
58122
|
refreshContainerStatus,
|
|
@@ -57801,6 +58129,7 @@ function createStoreResourceController(input) {
|
|
|
57801
58129
|
openAgentsOverlay,
|
|
57802
58130
|
openMcpOverlay,
|
|
57803
58131
|
openEmailOverlay,
|
|
58132
|
+
openSubagentsOverlay,
|
|
57804
58133
|
toggleContainer,
|
|
57805
58134
|
dispose: dispose2
|
|
57806
58135
|
};
|
|
@@ -58289,6 +58618,7 @@ function TuiStoreProvider(props) {
|
|
|
58289
58618
|
refreshAgentThreads: resources.refreshAgentThreads,
|
|
58290
58619
|
openAgentsOverlay: resources.openAgentsOverlay,
|
|
58291
58620
|
openMcpOverlay: resources.openMcpOverlay,
|
|
58621
|
+
openSubagentsOverlay: resources.openSubagentsOverlay,
|
|
58292
58622
|
openEmailOverlay: resources.openEmailOverlay,
|
|
58293
58623
|
toggleContainer: resources.toggleContainer,
|
|
58294
58624
|
setStatusDetail: status.set
|
|
@@ -58653,7 +58983,7 @@ function defineDefaultCommands(openers = {}) {
|
|
|
58653
58983
|
}) => {
|
|
58654
58984
|
tui.toggleContainer();
|
|
58655
58985
|
}
|
|
58656
|
-
}, messageNavigation("next", undefined), messageNavigation("prev", undefined), slashPrompt("context", "inspect context", "show stored versus projected context and token budget"), slashLocal("model", "switch model", "choose a model or add a provider", () => openers.model?.(), "visible", ["models"]), slashLocal("mcp", "mcp servers", "show configured mcp server status", () => openers.mcp?.()), slashLocal("email", "email inboxes", "choose primary or secondary email and add imap accounts", () => openers.email?.()), slashPrompt("campaign", "campaign control", "start, pause, resume, inspect, or stop a durable campaign"), slashLocal("exit", "exit", "exit farai", ({
|
|
58986
|
+
}, messageNavigation("next", undefined), messageNavigation("prev", undefined), slashPrompt("context", "inspect context", "show stored versus projected context and token budget"), slashLocal("model", "switch model", "choose a model or add a provider", () => openers.model?.(), "visible", ["models"]), slashLocal("mcp", "mcp servers", "show configured mcp server status", () => openers.mcp?.()), slashLocal("subagents", "subagent lanes", "manage subagent roles (lanes): add, edit, or delete", () => openers.subagents?.(), "visible", ["lanes", "roles"]), slashLocal("email", "email inboxes", "choose primary or secondary email and add imap accounts", () => openers.email?.()), slashPrompt("campaign", "campaign control", "start, pause, resume, inspect, or stop a durable campaign"), slashLocal("exit", "exit", "exit farai", ({
|
|
58657
58987
|
exit
|
|
58658
58988
|
}) => {
|
|
58659
58989
|
exit();
|
|
@@ -58897,6 +59227,10 @@ function routeKey(key, ctx) {
|
|
|
58897
59227
|
return routeModelProviderRemoval(key, ctx.modelProviderRemoval);
|
|
58898
59228
|
if (ctx.modelProviderWizard)
|
|
58899
59229
|
return routeModelProviderWizard(key, ctx.modelProviderWizard);
|
|
59230
|
+
if (ctx.laneRemoval)
|
|
59231
|
+
return routeLaneRemoval(key, ctx.laneRemoval);
|
|
59232
|
+
if (ctx.laneWizard)
|
|
59233
|
+
return routeLaneWizard(key, ctx.laneWizard);
|
|
58900
59234
|
if (ctx.pendingUserInput && key.ctrl && key.name === "q")
|
|
58901
59235
|
return consumed({
|
|
58902
59236
|
kind: "requestUserInput.show"
|
|
@@ -58904,7 +59238,7 @@ function routeKey(key, ctx) {
|
|
|
58904
59238
|
if (ctx.requestUserInput)
|
|
58905
59239
|
return routeRequestUserInput(key, ctx.requestUserInput);
|
|
58906
59240
|
if (ctx.overlayKind)
|
|
58907
|
-
return routeOverlay(key, ctx.overlayKind, ctx.modelOverlay, ctx.mcpOverlay, ctx.emailOverlay);
|
|
59241
|
+
return routeOverlay(key, ctx.overlayKind, ctx.modelOverlay, ctx.mcpOverlay, ctx.emailOverlay, ctx.subagentsOverlay);
|
|
58908
59242
|
if (ctx.centerSurfaceKind)
|
|
58909
59243
|
return routeCenterSurface(key, ctx.centerSurfaceKind, ctx.centerProxyFlowKind, ctx.centerSurfaceBusy);
|
|
58910
59244
|
if (ctx.historySearchActive)
|
|
@@ -59289,6 +59623,80 @@ function routeModelProviderWizard(key, state) {
|
|
|
59289
59623
|
});
|
|
59290
59624
|
return PASSTHROUGH;
|
|
59291
59625
|
}
|
|
59626
|
+
function routeLaneRemoval(key, state) {
|
|
59627
|
+
if (state.busy)
|
|
59628
|
+
return consumed();
|
|
59629
|
+
if (key.name === "return")
|
|
59630
|
+
return consumed({
|
|
59631
|
+
kind: "laneRemoval.confirm"
|
|
59632
|
+
});
|
|
59633
|
+
if (key.name === "escape" || key.ctrl && key.name === "c")
|
|
59634
|
+
return consumed({
|
|
59635
|
+
kind: "laneRemoval.cancel"
|
|
59636
|
+
});
|
|
59637
|
+
return consumed();
|
|
59638
|
+
}
|
|
59639
|
+
function routeLaneWizard(key, state) {
|
|
59640
|
+
if (state.busy)
|
|
59641
|
+
return consumed();
|
|
59642
|
+
if (key.name === "escape")
|
|
59643
|
+
return consumed({
|
|
59644
|
+
kind: "lane.back"
|
|
59645
|
+
});
|
|
59646
|
+
if (state.field === "tools") {
|
|
59647
|
+
if (key.ctrl && key.name === "a")
|
|
59648
|
+
return consumed({
|
|
59649
|
+
kind: "lane.toolSelectAll"
|
|
59650
|
+
});
|
|
59651
|
+
if (key.name === "up")
|
|
59652
|
+
return consumed({
|
|
59653
|
+
kind: "lane.toolMove",
|
|
59654
|
+
delta: -1
|
|
59655
|
+
});
|
|
59656
|
+
if (key.name === "down")
|
|
59657
|
+
return consumed({
|
|
59658
|
+
kind: "lane.toolMove",
|
|
59659
|
+
delta: 1
|
|
59660
|
+
});
|
|
59661
|
+
if (key.name === "space" || key.char === " ")
|
|
59662
|
+
return consumed({
|
|
59663
|
+
kind: "lane.toolToggle"
|
|
59664
|
+
});
|
|
59665
|
+
if (key.name === "return")
|
|
59666
|
+
return consumed({
|
|
59667
|
+
kind: "lane.next"
|
|
59668
|
+
});
|
|
59669
|
+
if (key.name === "backspace")
|
|
59670
|
+
return consumed({
|
|
59671
|
+
kind: "lane.toolFilterBackspace"
|
|
59672
|
+
});
|
|
59673
|
+
if (key.char && !key.ctrl && !key.meta)
|
|
59674
|
+
return consumed({
|
|
59675
|
+
kind: "lane.toolFilterAppend",
|
|
59676
|
+
char: key.char
|
|
59677
|
+
});
|
|
59678
|
+
return consumed();
|
|
59679
|
+
}
|
|
59680
|
+
if (state.field === "prompt") {
|
|
59681
|
+
if (key.ctrl && key.name === "s")
|
|
59682
|
+
return consumed({
|
|
59683
|
+
kind: "lane.next"
|
|
59684
|
+
});
|
|
59685
|
+
return PASSTHROUGH;
|
|
59686
|
+
}
|
|
59687
|
+
if (state.field === "review") {
|
|
59688
|
+
if (key.name === "return")
|
|
59689
|
+
return consumed({
|
|
59690
|
+
kind: "lane.next"
|
|
59691
|
+
});
|
|
59692
|
+
return consumed();
|
|
59693
|
+
}
|
|
59694
|
+
if (key.name === "return")
|
|
59695
|
+
return consumed({
|
|
59696
|
+
kind: "lane.next"
|
|
59697
|
+
});
|
|
59698
|
+
return PASSTHROUGH;
|
|
59699
|
+
}
|
|
59292
59700
|
function routeRequestUserInput(key, state) {
|
|
59293
59701
|
if (state.submitting)
|
|
59294
59702
|
return consumed();
|
|
@@ -59372,7 +59780,7 @@ function routeRequestUserInput(key, state) {
|
|
|
59372
59780
|
}
|
|
59373
59781
|
}
|
|
59374
59782
|
}
|
|
59375
|
-
function routeOverlay(key, kind, model, mcp, email) {
|
|
59783
|
+
function routeOverlay(key, kind, model, mcp, email, subagents) {
|
|
59376
59784
|
if (key.ctrl && key.name === "c")
|
|
59377
59785
|
return consumed({
|
|
59378
59786
|
kind: "overlay.pop"
|
|
@@ -59448,6 +59856,20 @@ function routeOverlay(key, kind, model, mcp, email) {
|
|
|
59448
59856
|
kind: "mcp.removeServer"
|
|
59449
59857
|
});
|
|
59450
59858
|
}
|
|
59859
|
+
if (kind === "subagents" && key.ctrl) {
|
|
59860
|
+
if (key.name === "a")
|
|
59861
|
+
return consumed({
|
|
59862
|
+
kind: "subagents.add"
|
|
59863
|
+
});
|
|
59864
|
+
if (key.name === "e" && subagents?.editable)
|
|
59865
|
+
return consumed({
|
|
59866
|
+
kind: "subagents.edit"
|
|
59867
|
+
});
|
|
59868
|
+
if (key.name === "d" && subagents?.removable)
|
|
59869
|
+
return consumed({
|
|
59870
|
+
kind: "subagents.remove"
|
|
59871
|
+
});
|
|
59872
|
+
}
|
|
59451
59873
|
if (kind === "agents" && (key.name === "space" || key.char === " ")) {
|
|
59452
59874
|
return consumed({
|
|
59453
59875
|
kind: "overlay.agentPreview"
|
|
@@ -59918,7 +60340,7 @@ function routeHistorySearch(key) {
|
|
|
59918
60340
|
var LIST_OVERLAYS, NAME_ALIASES, PASSTHROUGH;
|
|
59919
60341
|
var init_router = __esm(() => {
|
|
59920
60342
|
init_slash_autocomplete();
|
|
59921
|
-
LIST_OVERLAYS = new Set(["palette", "sessions", "evidence", "findings", "memory", "agents", "model", "mcp", "email"]);
|
|
60343
|
+
LIST_OVERLAYS = new Set(["palette", "sessions", "evidence", "findings", "memory", "agents", "model", "mcp", "email", "subagents"]);
|
|
59922
60344
|
NAME_ALIASES = {
|
|
59923
60345
|
enter: "return",
|
|
59924
60346
|
esc: "escape",
|
|
@@ -60006,6 +60428,17 @@ function buildRouterContext(input) {
|
|
|
60006
60428
|
busy: tui.store.ui.emailAccountRemoval.busy
|
|
60007
60429
|
}
|
|
60008
60430
|
} : {},
|
|
60431
|
+
...tui.store.ui.laneWizard ? {
|
|
60432
|
+
laneWizard: {
|
|
60433
|
+
field: tui.store.ui.laneWizard.field,
|
|
60434
|
+
busy: tui.store.ui.laneWizard.busy
|
|
60435
|
+
}
|
|
60436
|
+
} : {},
|
|
60437
|
+
...tui.store.ui.laneRemoval ? {
|
|
60438
|
+
laneRemoval: {
|
|
60439
|
+
busy: tui.store.ui.laneRemoval.busy
|
|
60440
|
+
}
|
|
60441
|
+
} : {},
|
|
60009
60442
|
...input.modelOverlay ? {
|
|
60010
60443
|
modelOverlay: input.modelOverlay
|
|
60011
60444
|
} : {},
|
|
@@ -60014,6 +60447,9 @@ function buildRouterContext(input) {
|
|
|
60014
60447
|
} : {},
|
|
60015
60448
|
...input.emailOverlay ? {
|
|
60016
60449
|
emailOverlay: input.emailOverlay
|
|
60450
|
+
} : {},
|
|
60451
|
+
...input.subagentsOverlay ? {
|
|
60452
|
+
subagentsOverlay: input.subagentsOverlay
|
|
60017
60453
|
} : {}
|
|
60018
60454
|
};
|
|
60019
60455
|
}
|
|
@@ -60083,6 +60519,30 @@ function overlayOptions(frame, tui, ctx) {
|
|
|
60083
60519
|
footer: new Date(item.updatedAt).toLocaleString(),
|
|
60084
60520
|
value: item.id
|
|
60085
60521
|
}));
|
|
60522
|
+
case "subagents": {
|
|
60523
|
+
const laneRows = tui.store.ui.lanes.map((lane) => ({
|
|
60524
|
+
id: lane.id,
|
|
60525
|
+
title: lane.id,
|
|
60526
|
+
description: `${lane.description ?? "custom lane"}${lane.tools?.length ? ` \xB7 ${lane.tools.length} tools` : ""}${lane.model ? ` \xB7 ${lane.model}` : ""}`,
|
|
60527
|
+
badge: lane.source === "builtin" ? "builtin" : lane.source === "workspace" ? "project" : "custom",
|
|
60528
|
+
value: {
|
|
60529
|
+
kind: "lane",
|
|
60530
|
+
laneId: lane.id,
|
|
60531
|
+
editable: lane.editable
|
|
60532
|
+
}
|
|
60533
|
+
}));
|
|
60534
|
+
return [...laneRows, {
|
|
60535
|
+
id: "lane:add",
|
|
60536
|
+
title: "+ add lane",
|
|
60537
|
+
description: "create a new subagent role",
|
|
60538
|
+
numbered: false,
|
|
60539
|
+
separatorBefore: true,
|
|
60540
|
+
value: {
|
|
60541
|
+
kind: "lane_action",
|
|
60542
|
+
action: "add"
|
|
60543
|
+
}
|
|
60544
|
+
}];
|
|
60545
|
+
}
|
|
60086
60546
|
case "model": {
|
|
60087
60547
|
const session = tui.store.snapshot.session;
|
|
60088
60548
|
if (tui.store.ui.availableModels.length === 0 && tui.store.ui.statusDetail === "loading models") {
|
|
@@ -60366,6 +60826,8 @@ function overlayTitle(frame) {
|
|
|
60366
60826
|
return "mcp servers";
|
|
60367
60827
|
case "email":
|
|
60368
60828
|
return "email";
|
|
60829
|
+
case "subagents":
|
|
60830
|
+
return "subagent lanes";
|
|
60369
60831
|
}
|
|
60370
60832
|
}
|
|
60371
60833
|
var init_overlay_options = __esm(() => {
|
|
@@ -60418,6 +60880,15 @@ function createOverlaySelection(tui, commandContext) {
|
|
|
60418
60880
|
return;
|
|
60419
60881
|
return tui.store.ui.emailAccounts.find((account) => account.id === choice.emailId);
|
|
60420
60882
|
}
|
|
60883
|
+
function lane() {
|
|
60884
|
+
const frame = tui.store.ui.overlayStack.at(-1);
|
|
60885
|
+
if (frame?.kind !== "subagents")
|
|
60886
|
+
return;
|
|
60887
|
+
const choice = selectedOption()?.value;
|
|
60888
|
+
if (choice?.kind !== "lane")
|
|
60889
|
+
return;
|
|
60890
|
+
return tui.store.ui.lanes.find((item) => item.id === choice.laneId);
|
|
60891
|
+
}
|
|
60421
60892
|
function selectedEmail() {
|
|
60422
60893
|
const frame = tui.store.ui.overlayStack.at(-1);
|
|
60423
60894
|
if (frame?.kind !== "email")
|
|
@@ -60451,6 +60922,18 @@ function createOverlaySelection(tui, commandContext) {
|
|
|
60451
60922
|
removable: false
|
|
60452
60923
|
};
|
|
60453
60924
|
},
|
|
60925
|
+
lane,
|
|
60926
|
+
laneContext: () => {
|
|
60927
|
+
const item = lane();
|
|
60928
|
+
return item ? {
|
|
60929
|
+
laneId: item.id,
|
|
60930
|
+
editable: item.editable,
|
|
60931
|
+
removable: item.source === "global"
|
|
60932
|
+
} : {
|
|
60933
|
+
editable: false,
|
|
60934
|
+
removable: false
|
|
60935
|
+
};
|
|
60936
|
+
},
|
|
60454
60937
|
emailAccount,
|
|
60455
60938
|
selectedEmail,
|
|
60456
60939
|
emailContext: () => {
|
|
@@ -61600,6 +62083,260 @@ var init_email_account_controller = __esm(() => {
|
|
|
61600
62083
|
init_accounts();
|
|
61601
62084
|
});
|
|
61602
62085
|
|
|
62086
|
+
// src/agent-tui/input/lane-controller.ts
|
|
62087
|
+
function createLaneController(input) {
|
|
62088
|
+
const {
|
|
62089
|
+
tui,
|
|
62090
|
+
port,
|
|
62091
|
+
selection
|
|
62092
|
+
} = input;
|
|
62093
|
+
const operations = createControllerOperations(tui);
|
|
62094
|
+
function overlayOpen() {
|
|
62095
|
+
return tui.store.ui.overlayStack.at(-1)?.kind === "subagents";
|
|
62096
|
+
}
|
|
62097
|
+
function reopen() {
|
|
62098
|
+
tui.actions.overlayClear();
|
|
62099
|
+
tui.actions.overlayPush({
|
|
62100
|
+
kind: "subagents",
|
|
62101
|
+
query: "",
|
|
62102
|
+
index: 0
|
|
62103
|
+
});
|
|
62104
|
+
}
|
|
62105
|
+
function openAdd() {
|
|
62106
|
+
operations.invalidate();
|
|
62107
|
+
tui.actions.laneWizardOpen();
|
|
62108
|
+
}
|
|
62109
|
+
function openEdit() {
|
|
62110
|
+
const lane = selection.lane();
|
|
62111
|
+
if (!lane?.editable)
|
|
62112
|
+
return;
|
|
62113
|
+
operations.invalidate();
|
|
62114
|
+
tui.actions.laneWizardOpen(lane);
|
|
62115
|
+
}
|
|
62116
|
+
function requestRemoval() {
|
|
62117
|
+
const lane = selection.lane();
|
|
62118
|
+
if (lane && lane.source === "global")
|
|
62119
|
+
tui.actions.laneRemovalOpen(lane);
|
|
62120
|
+
}
|
|
62121
|
+
async function confirmRemoval() {
|
|
62122
|
+
const removalState = tui.store.ui.laneRemoval;
|
|
62123
|
+
if (!removalState || removalState.busy)
|
|
62124
|
+
return;
|
|
62125
|
+
const operation = operations.begin();
|
|
62126
|
+
tui.actions.laneRemovalPatch({
|
|
62127
|
+
busy: true,
|
|
62128
|
+
error: undefined
|
|
62129
|
+
});
|
|
62130
|
+
let lanes;
|
|
62131
|
+
try {
|
|
62132
|
+
lanes = await port.removeLane(removalState.lane.id);
|
|
62133
|
+
} catch (error) {
|
|
62134
|
+
if (!operations.owns(operation) || input.isDisposed())
|
|
62135
|
+
return;
|
|
62136
|
+
if (tui.store.ui.laneRemoval?.lane.id !== removalState.lane.id)
|
|
62137
|
+
return;
|
|
62138
|
+
tui.actions.laneRemovalPatch({
|
|
62139
|
+
busy: false,
|
|
62140
|
+
error: error instanceof Error ? error.message : String(error)
|
|
62141
|
+
});
|
|
62142
|
+
return;
|
|
62143
|
+
}
|
|
62144
|
+
if (!operations.owns(operation) || input.isDisposed() || tui.store.ui.laneRemoval?.lane.id !== removalState.lane.id)
|
|
62145
|
+
return;
|
|
62146
|
+
tui.actions.laneRemovalClose();
|
|
62147
|
+
tui.actions.lanesSet(lanes);
|
|
62148
|
+
reopen();
|
|
62149
|
+
tui.setStatusDetail(`removed lane ${removalState.lane.id}`, 3000);
|
|
62150
|
+
}
|
|
62151
|
+
function cancelRemoval() {
|
|
62152
|
+
operations.invalidate();
|
|
62153
|
+
tui.actions.laneRemovalClose();
|
|
62154
|
+
}
|
|
62155
|
+
async function next() {
|
|
62156
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62157
|
+
if (!wizard || wizard.busy)
|
|
62158
|
+
return;
|
|
62159
|
+
tui.actions.laneWizardPatch({
|
|
62160
|
+
error: undefined
|
|
62161
|
+
});
|
|
62162
|
+
if (wizard.field === "id") {
|
|
62163
|
+
const normalized = wizard.id.trim().toLowerCase();
|
|
62164
|
+
if (!LANE_ID2.test(normalized)) {
|
|
62165
|
+
tui.actions.laneWizardPatch({
|
|
62166
|
+
error: "lane id must match a-z 0-9 _ - and start alphanumeric"
|
|
62167
|
+
});
|
|
62168
|
+
return;
|
|
62169
|
+
}
|
|
62170
|
+
if (wizard.mode === "add" && tui.store.ui.lanes.some((lane) => lane.id === normalized && lane.source !== "builtin")) {
|
|
62171
|
+
tui.actions.laneWizardPatch({
|
|
62172
|
+
error: `${normalized} already exists \xB7 select it and press ctrl+e to edit`
|
|
62173
|
+
});
|
|
62174
|
+
return;
|
|
62175
|
+
}
|
|
62176
|
+
tui.actions.laneWizardPatch({
|
|
62177
|
+
id: normalized,
|
|
62178
|
+
field: "description"
|
|
62179
|
+
});
|
|
62180
|
+
return;
|
|
62181
|
+
}
|
|
62182
|
+
if (wizard.field === "description") {
|
|
62183
|
+
tui.actions.laneWizardPatch({
|
|
62184
|
+
field: "prompt"
|
|
62185
|
+
});
|
|
62186
|
+
return;
|
|
62187
|
+
}
|
|
62188
|
+
if (wizard.field === "prompt") {
|
|
62189
|
+
tui.actions.laneWizardPatch({
|
|
62190
|
+
field: "tools",
|
|
62191
|
+
toolFilter: "",
|
|
62192
|
+
toolCursor: 0
|
|
62193
|
+
});
|
|
62194
|
+
return;
|
|
62195
|
+
}
|
|
62196
|
+
if (wizard.field === "tools") {
|
|
62197
|
+
tui.actions.laneWizardPatch({
|
|
62198
|
+
field: "model"
|
|
62199
|
+
});
|
|
62200
|
+
return;
|
|
62201
|
+
}
|
|
62202
|
+
if (wizard.field === "model") {
|
|
62203
|
+
tui.actions.laneWizardPatch({
|
|
62204
|
+
field: "review"
|
|
62205
|
+
});
|
|
62206
|
+
return;
|
|
62207
|
+
}
|
|
62208
|
+
const operation = operations.begin();
|
|
62209
|
+
tui.actions.laneWizardPatch({
|
|
62210
|
+
busy: true,
|
|
62211
|
+
error: undefined
|
|
62212
|
+
});
|
|
62213
|
+
try {
|
|
62214
|
+
const lanes = await port.saveLane({
|
|
62215
|
+
id: wizard.id,
|
|
62216
|
+
...wizard.description.trim() ? {
|
|
62217
|
+
description: wizard.description.trim()
|
|
62218
|
+
} : {},
|
|
62219
|
+
...wizard.prompt.trim() ? {
|
|
62220
|
+
prompt: wizard.prompt.trim()
|
|
62221
|
+
} : {},
|
|
62222
|
+
...wizard.tools.length ? {
|
|
62223
|
+
tools: wizard.tools
|
|
62224
|
+
} : {},
|
|
62225
|
+
...wizard.model.trim() ? {
|
|
62226
|
+
model: wizard.model.trim()
|
|
62227
|
+
} : {}
|
|
62228
|
+
});
|
|
62229
|
+
if (!operations.owns(operation) || input.isDisposed() || !tui.store.ui.laneWizard)
|
|
62230
|
+
return;
|
|
62231
|
+
tui.actions.lanesSet(lanes);
|
|
62232
|
+
tui.actions.laneWizardClose();
|
|
62233
|
+
if (overlayOpen())
|
|
62234
|
+
reopen();
|
|
62235
|
+
tui.setStatusDetail(`lane ${wizard.id} saved`, 3000);
|
|
62236
|
+
} catch (error) {
|
|
62237
|
+
if (!operations.owns(operation) || input.isDisposed() || !tui.store.ui.laneWizard)
|
|
62238
|
+
return;
|
|
62239
|
+
tui.actions.laneWizardPatch({
|
|
62240
|
+
busy: false,
|
|
62241
|
+
error: error instanceof Error ? error.message : String(error)
|
|
62242
|
+
});
|
|
62243
|
+
}
|
|
62244
|
+
}
|
|
62245
|
+
function visibleTools() {
|
|
62246
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62247
|
+
return wizard ? filteredToolNames(tui.store.ui.toolNames, wizard.toolFilter) : [];
|
|
62248
|
+
}
|
|
62249
|
+
function moveTool(delta) {
|
|
62250
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62251
|
+
if (!wizard)
|
|
62252
|
+
return;
|
|
62253
|
+
const count2 = visibleTools().length;
|
|
62254
|
+
if (count2 === 0)
|
|
62255
|
+
return;
|
|
62256
|
+
tui.actions.laneWizardPatch({
|
|
62257
|
+
toolCursor: Math.max(0, Math.min(count2 - 1, wizard.toolCursor + delta))
|
|
62258
|
+
});
|
|
62259
|
+
}
|
|
62260
|
+
function toggleTool() {
|
|
62261
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62262
|
+
if (!wizard)
|
|
62263
|
+
return;
|
|
62264
|
+
const tools = visibleTools();
|
|
62265
|
+
const name = tools[Math.max(0, Math.min(tools.length - 1, wizard.toolCursor))];
|
|
62266
|
+
if (!name)
|
|
62267
|
+
return;
|
|
62268
|
+
const next2 = wizard.tools.includes(name) ? wizard.tools.filter((tool) => tool !== name) : [...wizard.tools, name];
|
|
62269
|
+
tui.actions.laneWizardPatch({
|
|
62270
|
+
tools: next2
|
|
62271
|
+
});
|
|
62272
|
+
}
|
|
62273
|
+
function selectAllTools() {
|
|
62274
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62275
|
+
if (!wizard)
|
|
62276
|
+
return;
|
|
62277
|
+
const visible = visibleTools();
|
|
62278
|
+
if (visible.length === 0)
|
|
62279
|
+
return;
|
|
62280
|
+
const allSelected = visible.every((name) => wizard.tools.includes(name));
|
|
62281
|
+
const next2 = allSelected ? wizard.tools.filter((name) => !visible.includes(name)) : [...new Set([...wizard.tools, ...visible])];
|
|
62282
|
+
tui.actions.laneWizardPatch({
|
|
62283
|
+
tools: next2
|
|
62284
|
+
});
|
|
62285
|
+
}
|
|
62286
|
+
function filterAppend(char) {
|
|
62287
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62288
|
+
if (!wizard)
|
|
62289
|
+
return;
|
|
62290
|
+
tui.actions.laneWizardPatch({
|
|
62291
|
+
toolFilter: `${wizard.toolFilter}${char}`,
|
|
62292
|
+
toolCursor: 0
|
|
62293
|
+
});
|
|
62294
|
+
}
|
|
62295
|
+
function filterBackspace() {
|
|
62296
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62297
|
+
if (!wizard?.toolFilter)
|
|
62298
|
+
return;
|
|
62299
|
+
tui.actions.laneWizardPatch({
|
|
62300
|
+
toolFilter: [...wizard.toolFilter].slice(0, -1).join(""),
|
|
62301
|
+
toolCursor: 0
|
|
62302
|
+
});
|
|
62303
|
+
}
|
|
62304
|
+
function back() {
|
|
62305
|
+
const wizard = tui.store.ui.laneWizard;
|
|
62306
|
+
if (!wizard || wizard.busy)
|
|
62307
|
+
return;
|
|
62308
|
+
if (wizard.mode === "add" && wizard.field === "id" || wizard.mode === "edit" && wizard.field === "description") {
|
|
62309
|
+
operations.invalidate();
|
|
62310
|
+
tui.actions.laneWizardClose();
|
|
62311
|
+
return;
|
|
62312
|
+
}
|
|
62313
|
+
tui.actions.laneWizardPatch({
|
|
62314
|
+
field: laneWizardFieldMove(wizard.field, -1),
|
|
62315
|
+
error: undefined
|
|
62316
|
+
});
|
|
62317
|
+
}
|
|
62318
|
+
return {
|
|
62319
|
+
dispose: () => operations.invalidate(),
|
|
62320
|
+
openAdd,
|
|
62321
|
+
openEdit,
|
|
62322
|
+
requestRemoval,
|
|
62323
|
+
confirmRemoval,
|
|
62324
|
+
cancelRemoval,
|
|
62325
|
+
next,
|
|
62326
|
+
back,
|
|
62327
|
+
moveTool,
|
|
62328
|
+
toggleTool,
|
|
62329
|
+
selectAllTools,
|
|
62330
|
+
filterAppend,
|
|
62331
|
+
filterBackspace
|
|
62332
|
+
};
|
|
62333
|
+
}
|
|
62334
|
+
var LANE_ID2;
|
|
62335
|
+
var init_lane_controller = __esm(() => {
|
|
62336
|
+
init_lane_state();
|
|
62337
|
+
LANE_ID2 = /^[a-z0-9][a-z0-9_-]*$/;
|
|
62338
|
+
});
|
|
62339
|
+
|
|
61603
62340
|
// src/agent-tui/input/request-user-input-controller.ts
|
|
61604
62341
|
function createRequestUserInputController(tui, focusComposer) {
|
|
61605
62342
|
function current() {
|
|
@@ -61893,6 +62630,14 @@ function createOverlayController(input) {
|
|
|
61893
62630
|
input.openEmailAccount?.();
|
|
61894
62631
|
return;
|
|
61895
62632
|
}
|
|
62633
|
+
case "subagents": {
|
|
62634
|
+
const choice = option.value;
|
|
62635
|
+
if (choice.kind === "lane_action")
|
|
62636
|
+
input.openLaneAdd?.();
|
|
62637
|
+
else if (choice.editable)
|
|
62638
|
+
input.openLaneEdit?.();
|
|
62639
|
+
return;
|
|
62640
|
+
}
|
|
61896
62641
|
case "model": {
|
|
61897
62642
|
const choice = option.value;
|
|
61898
62643
|
if (choice.kind === "model_action") {
|
|
@@ -62862,6 +63607,12 @@ function KeyboardController() {
|
|
|
62862
63607
|
selection: overlaySelection,
|
|
62863
63608
|
isDisposed: () => disposed
|
|
62864
63609
|
});
|
|
63610
|
+
const lane = createLaneController({
|
|
63611
|
+
tui,
|
|
63612
|
+
port,
|
|
63613
|
+
selection: overlaySelection,
|
|
63614
|
+
isDisposed: () => disposed
|
|
63615
|
+
});
|
|
62865
63616
|
const requestUserInput = createRequestUserInputController(tui, () => composer.focus());
|
|
62866
63617
|
const centerSurface = createCenterSurfaceController({
|
|
62867
63618
|
tui,
|
|
@@ -62904,7 +63655,9 @@ function KeyboardController() {
|
|
|
62904
63655
|
owns: ownsSession,
|
|
62905
63656
|
openModelProvider: modelProvider.openAdd,
|
|
62906
63657
|
openMcpServer: mcpServer.openAdd,
|
|
62907
|
-
openEmailAccount: emailAccount.openAdd
|
|
63658
|
+
openEmailAccount: emailAccount.openAdd,
|
|
63659
|
+
openLaneAdd: lane.openAdd,
|
|
63660
|
+
openLaneEdit: lane.openEdit
|
|
62908
63661
|
});
|
|
62909
63662
|
let modelOverlayKey;
|
|
62910
63663
|
let mcpOverlayKey;
|
|
@@ -62965,6 +63718,9 @@ function KeyboardController() {
|
|
|
62965
63718
|
} : {},
|
|
62966
63719
|
...top?.kind === "email" ? {
|
|
62967
63720
|
emailOverlay: overlaySelection.emailContext()
|
|
63721
|
+
} : {},
|
|
63722
|
+
...top?.kind === "subagents" ? {
|
|
63723
|
+
subagentsOverlay: overlaySelection.laneContext()
|
|
62968
63724
|
} : {}
|
|
62969
63725
|
}));
|
|
62970
63726
|
if (routed.type === "passthrough")
|
|
@@ -62993,6 +63749,7 @@ function KeyboardController() {
|
|
|
62993
63749
|
modelProvider.dispose();
|
|
62994
63750
|
mcpServer.dispose();
|
|
62995
63751
|
emailAccount.dispose();
|
|
63752
|
+
lane.dispose();
|
|
62996
63753
|
});
|
|
62997
63754
|
function dispatchAction(action) {
|
|
62998
63755
|
applyAction(action).catch((error) => {
|
|
@@ -63161,6 +63918,42 @@ function KeyboardController() {
|
|
|
63161
63918
|
case "mcp.removeServer":
|
|
63162
63919
|
mcpServer.requestRemoval();
|
|
63163
63920
|
return;
|
|
63921
|
+
case "lane.next":
|
|
63922
|
+
await lane.next();
|
|
63923
|
+
return;
|
|
63924
|
+
case "lane.back":
|
|
63925
|
+
lane.back();
|
|
63926
|
+
return;
|
|
63927
|
+
case "lane.toolMove":
|
|
63928
|
+
lane.moveTool(action.delta);
|
|
63929
|
+
return;
|
|
63930
|
+
case "lane.toolToggle":
|
|
63931
|
+
lane.toggleTool();
|
|
63932
|
+
return;
|
|
63933
|
+
case "lane.toolSelectAll":
|
|
63934
|
+
lane.selectAllTools();
|
|
63935
|
+
return;
|
|
63936
|
+
case "lane.toolFilterAppend":
|
|
63937
|
+
lane.filterAppend(action.char);
|
|
63938
|
+
return;
|
|
63939
|
+
case "lane.toolFilterBackspace":
|
|
63940
|
+
lane.filterBackspace();
|
|
63941
|
+
return;
|
|
63942
|
+
case "laneRemoval.confirm":
|
|
63943
|
+
await lane.confirmRemoval();
|
|
63944
|
+
return;
|
|
63945
|
+
case "laneRemoval.cancel":
|
|
63946
|
+
lane.cancelRemoval();
|
|
63947
|
+
return;
|
|
63948
|
+
case "subagents.add":
|
|
63949
|
+
lane.openAdd();
|
|
63950
|
+
return;
|
|
63951
|
+
case "subagents.edit":
|
|
63952
|
+
lane.openEdit();
|
|
63953
|
+
return;
|
|
63954
|
+
case "subagents.remove":
|
|
63955
|
+
lane.requestRemoval();
|
|
63956
|
+
return;
|
|
63164
63957
|
case "composer.submit":
|
|
63165
63958
|
await composerActions.submit();
|
|
63166
63959
|
return;
|
|
@@ -63343,6 +64136,7 @@ var init_keyboard_controller = __esm(() => {
|
|
|
63343
64136
|
init_model_provider_controller();
|
|
63344
64137
|
init_mcp_server_controller();
|
|
63345
64138
|
init_email_account_controller();
|
|
64139
|
+
init_lane_controller();
|
|
63346
64140
|
init_request_user_input_controller();
|
|
63347
64141
|
init_center_surface_controller();
|
|
63348
64142
|
init_overlay_controller();
|
|
@@ -63353,6 +64147,28 @@ var init_keyboard_controller = __esm(() => {
|
|
|
63353
64147
|
});
|
|
63354
64148
|
|
|
63355
64149
|
// src/agent-tui/theme.ts
|
|
64150
|
+
function toolFamilyColor(family) {
|
|
64151
|
+
switch (family) {
|
|
64152
|
+
case "workspace":
|
|
64153
|
+
return COLOR.success;
|
|
64154
|
+
case "recon":
|
|
64155
|
+
case "http":
|
|
64156
|
+
return COLOR.info;
|
|
64157
|
+
case "browser":
|
|
64158
|
+
return COLOR.accent;
|
|
64159
|
+
case "knowledge":
|
|
64160
|
+
return COLOR.agent;
|
|
64161
|
+
case "proxy":
|
|
64162
|
+
return COLOR.memory.endpoint;
|
|
64163
|
+
case "campaign":
|
|
64164
|
+
case "agent":
|
|
64165
|
+
return COLOR.memory.hypothesis;
|
|
64166
|
+
case "command":
|
|
64167
|
+
return COLOR.warning;
|
|
64168
|
+
default:
|
|
64169
|
+
return COLOR.text;
|
|
64170
|
+
}
|
|
64171
|
+
}
|
|
63356
64172
|
var COLOR;
|
|
63357
64173
|
var init_theme = __esm(() => {
|
|
63358
64174
|
init_tool_presentation();
|
|
@@ -63361,6 +64177,8 @@ var init_theme = __esm(() => {
|
|
|
63361
64177
|
muted: "#a8a8a8",
|
|
63362
64178
|
text: "#d7d7d7",
|
|
63363
64179
|
accent: "#5fd7ff",
|
|
64180
|
+
agent: "#b39ddb",
|
|
64181
|
+
info: "#7cb7ff",
|
|
63364
64182
|
warning: "#d7af5f",
|
|
63365
64183
|
error: "#ff5f5f",
|
|
63366
64184
|
success: "#87d75f",
|
|
@@ -64789,7 +65607,7 @@ function AssistantMessage(props) {
|
|
|
64789
65607
|
});
|
|
64790
65608
|
insert(_el$2, createComponent2(TranscriptMarker, {
|
|
64791
65609
|
get color() {
|
|
64792
|
-
return COLOR.
|
|
65610
|
+
return COLOR.agent;
|
|
64793
65611
|
}
|
|
64794
65612
|
}), _el$3);
|
|
64795
65613
|
setProp(_el$3, "style", {
|
|
@@ -65084,7 +65902,7 @@ function StandardToolRow(props) {
|
|
|
65084
65902
|
const right = [presentation().showOutcome !== false ? presentation().outcome : undefined, formatActivityDuration(props.row.durationMs)].filter(Boolean).join(" \xB7 ");
|
|
65085
65903
|
return fitTerminalPair(title, right, Math.max(1, dims().width - 4), 8, 2);
|
|
65086
65904
|
};
|
|
65087
|
-
const headerColor = () => active() ? COLOR.accent : toolColor(props.row.status);
|
|
65905
|
+
const headerColor = () => active() ? COLOR.accent : toolColor(props.row.status, props.row.tool);
|
|
65088
65906
|
const toggleClick = createPrimaryClickGesture(() => tui.actions.cellExpandedToggle(props.row.id));
|
|
65089
65907
|
const previewClick = createPrimaryClickGesture(() => tui.actions.cellExpandedToggle(props.row.id));
|
|
65090
65908
|
const semanticPreview = () => presentation().preview.filter((line) => line.trim() !== presentation().outcome?.trim());
|
|
@@ -65328,7 +66146,8 @@ function ActivityRow(props) {
|
|
|
65328
66146
|
},
|
|
65329
66147
|
children: (item, index) => {
|
|
65330
66148
|
const presentation = () => item.presentation ?? presentToolActivity(item);
|
|
65331
|
-
const
|
|
66149
|
+
const compact = () => presentation().groupItem ?? presentation().compact;
|
|
66150
|
+
const pair = () => fitTerminalPair(compact(), presentation().showOutcome !== false ? presentation().outcome ?? "" : "", width(), 8, 3);
|
|
65332
66151
|
return (() => {
|
|
65333
66152
|
var _el$20 = createElement("box"), _el$21 = createElement("text"), _el$22 = createElement("text");
|
|
65334
66153
|
insertNode(_el$20, _el$21);
|
|
@@ -66136,11 +66955,11 @@ function previewOutputLines(text2, limit) {
|
|
|
66136
66955
|
const tail = Math.max(1, limit - head - 1);
|
|
66137
66956
|
return [...lines.slice(0, head), `\u2026 +${lines.length - head - tail} lines (ctrl+t for full transcript)`, ...lines.slice(lines.length - tail)];
|
|
66138
66957
|
}
|
|
66139
|
-
function toolColor(status) {
|
|
66958
|
+
function toolColor(status, tool) {
|
|
66140
66959
|
if (status === "failed" || status === "error" || status === "denied")
|
|
66141
66960
|
return COLOR.error;
|
|
66142
66961
|
if (status === "done")
|
|
66143
|
-
return COLOR.text;
|
|
66962
|
+
return tool ? toolFamilyColor(toolLifecycleFamily(tool)) : COLOR.text;
|
|
66144
66963
|
return COLOR.dim;
|
|
66145
66964
|
}
|
|
66146
66965
|
function looksLikeDiff(text2) {
|
|
@@ -66255,6 +67074,7 @@ var init_tool_cell = __esm(() => {
|
|
|
66255
67074
|
init_filetype();
|
|
66256
67075
|
init_syntax();
|
|
66257
67076
|
init_theme();
|
|
67077
|
+
init_tool_lifecycle();
|
|
66258
67078
|
init_terminal();
|
|
66259
67079
|
init_store4();
|
|
66260
67080
|
init_tool_presentation();
|
|
@@ -66283,13 +67103,14 @@ function NoticeRow(props) {
|
|
|
66283
67103
|
};
|
|
66284
67104
|
const label = () => {
|
|
66285
67105
|
if (props.row.kind === "compaction")
|
|
66286
|
-
return "compacted
|
|
67106
|
+
return "compacted";
|
|
66287
67107
|
if (props.row.kind === "loop_stop")
|
|
66288
67108
|
return props.row.reason;
|
|
66289
67109
|
if (props.row.kind === "notice")
|
|
66290
67110
|
return props.row.title;
|
|
66291
67111
|
return props.row.title;
|
|
66292
67112
|
};
|
|
67113
|
+
const references = () => props.row.kind === "compaction" ? props.row.references ?? [] : [];
|
|
66293
67114
|
const detail = () => props.row.kind === "notice" ? props.row.detail : props.row.text;
|
|
66294
67115
|
const body = () => {
|
|
66295
67116
|
if (props.row.kind === "compaction")
|
|
@@ -66337,6 +67158,30 @@ function NoticeRow(props) {
|
|
|
66337
67158
|
return _el$4;
|
|
66338
67159
|
}
|
|
66339
67160
|
}), null);
|
|
67161
|
+
insert(_el$, createComponent2(Show, {
|
|
67162
|
+
get when() {
|
|
67163
|
+
return references().length > 0;
|
|
67164
|
+
},
|
|
67165
|
+
get children() {
|
|
67166
|
+
var _el$6 = createElement("box");
|
|
67167
|
+
setProp(_el$6, "style", {
|
|
67168
|
+
flexDirection: "column",
|
|
67169
|
+
paddingLeft: 2
|
|
67170
|
+
});
|
|
67171
|
+
insert(_el$6, createComponent2(For, {
|
|
67172
|
+
get each() {
|
|
67173
|
+
return references();
|
|
67174
|
+
},
|
|
67175
|
+
children: (reference, index) => (() => {
|
|
67176
|
+
var _el$7 = createElement("text");
|
|
67177
|
+
insert(_el$7, () => `${index() === 0 ? "\u2514 " : " "}${reference}`);
|
|
67178
|
+
effect((_$p) => setProp(_el$7, "fg", COLOR.dim, _$p));
|
|
67179
|
+
return _el$7;
|
|
67180
|
+
})()
|
|
67181
|
+
}));
|
|
67182
|
+
return _el$6;
|
|
67183
|
+
}
|
|
67184
|
+
}), null);
|
|
66340
67185
|
insert(_el$, createComponent2(Show, {
|
|
66341
67186
|
get when() {
|
|
66342
67187
|
return memo2(() => !!expanded())() && body();
|
|
@@ -66879,7 +67724,7 @@ function PhaseRow(props) {
|
|
|
66879
67724
|
marginBottom: 1
|
|
66880
67725
|
});
|
|
66881
67726
|
insert(_el$4, () => `\u2022 phase changed \xB7 ${props.row.phase}${props.row.detail ? ` \xB7 ${props.row.detail}` : ""}`);
|
|
66882
|
-
effect((_$p) => setProp(_el$4, "fg", COLOR.
|
|
67727
|
+
effect((_$p) => setProp(_el$4, "fg", COLOR.accent, _$p));
|
|
66883
67728
|
return _el$3;
|
|
66884
67729
|
})();
|
|
66885
67730
|
}
|
|
@@ -66997,23 +67842,32 @@ function ContextRow(props) {
|
|
|
66997
67842
|
},
|
|
66998
67843
|
get fallback() {
|
|
66999
67844
|
return (() => {
|
|
67000
|
-
var _el$
|
|
67001
|
-
insert(_el$
|
|
67002
|
-
return _el$
|
|
67845
|
+
var _el$12 = createElement("text");
|
|
67846
|
+
insert(_el$12, () => " ".repeat(columns() * 2));
|
|
67847
|
+
return _el$12;
|
|
67003
67848
|
})();
|
|
67004
67849
|
},
|
|
67005
67850
|
get children() {
|
|
67006
|
-
return createComponent2(For, {
|
|
67851
|
+
return [createComponent2(For, {
|
|
67007
67852
|
get each() {
|
|
67008
67853
|
return grid();
|
|
67009
67854
|
},
|
|
67010
67855
|
children: (tone) => (() => {
|
|
67011
|
-
var _el$
|
|
67012
|
-
insert(_el$
|
|
67013
|
-
effect((_$p) => setProp(_el$
|
|
67014
|
-
return _el$
|
|
67856
|
+
var _el$13 = createElement("text");
|
|
67857
|
+
insert(_el$13, tone === "free" ? "\u26F6 " : "\u26C1 ");
|
|
67858
|
+
effect((_$p) => setProp(_el$13, "fg", toneColor(tone), _$p));
|
|
67859
|
+
return _el$13;
|
|
67015
67860
|
})()
|
|
67016
|
-
})
|
|
67861
|
+
}), createComponent2(Show, {
|
|
67862
|
+
get when() {
|
|
67863
|
+
return grid().length < columns();
|
|
67864
|
+
},
|
|
67865
|
+
get children() {
|
|
67866
|
+
var _el$8 = createElement("text");
|
|
67867
|
+
insert(_el$8, () => " ".repeat((columns() - grid().length) * 2));
|
|
67868
|
+
return _el$8;
|
|
67869
|
+
}
|
|
67870
|
+
})];
|
|
67017
67871
|
}
|
|
67018
67872
|
}), null);
|
|
67019
67873
|
insert(_el$7, createComponent2(Show, {
|
|
@@ -67022,24 +67876,24 @@ function ContextRow(props) {
|
|
|
67022
67876
|
},
|
|
67023
67877
|
get children() {
|
|
67024
67878
|
return [(() => {
|
|
67025
|
-
var _el$
|
|
67026
|
-
insertNode(_el$
|
|
67027
|
-
return _el$
|
|
67879
|
+
var _el$9 = createElement("text");
|
|
67880
|
+
insertNode(_el$9, createTextNode(` `));
|
|
67881
|
+
return _el$9;
|
|
67028
67882
|
})(), createComponent2(Show, {
|
|
67029
67883
|
get when() {
|
|
67030
67884
|
return line().dot;
|
|
67031
67885
|
},
|
|
67032
67886
|
get children() {
|
|
67033
|
-
var _el$
|
|
67034
|
-
insertNode(_el$
|
|
67035
|
-
effect((_$p) => setProp(_el$
|
|
67036
|
-
return _el$
|
|
67887
|
+
var _el$1 = createElement("text");
|
|
67888
|
+
insertNode(_el$1, createTextNode(`\u26C1 `));
|
|
67889
|
+
effect((_$p) => setProp(_el$1, "fg", toneColor(line().dot), _$p));
|
|
67890
|
+
return _el$1;
|
|
67037
67891
|
}
|
|
67038
67892
|
}), (() => {
|
|
67039
|
-
var _el$
|
|
67040
|
-
insert(_el$
|
|
67041
|
-
effect((_$p) => setProp(_el$
|
|
67042
|
-
return _el$
|
|
67893
|
+
var _el$11 = createElement("text");
|
|
67894
|
+
insert(_el$11, () => line().text);
|
|
67895
|
+
effect((_$p) => setProp(_el$11, "fg", line().color, _$p));
|
|
67896
|
+
return _el$11;
|
|
67043
67897
|
})()];
|
|
67044
67898
|
}
|
|
67045
67899
|
}), null);
|
|
@@ -67210,6 +68064,32 @@ var init_cells = __esm(() => {
|
|
|
67210
68064
|
});
|
|
67211
68065
|
|
|
67212
68066
|
// src/agent-tui/transcript/transcript.tsx
|
|
68067
|
+
function compactReferences(toolCalls) {
|
|
68068
|
+
const verbs = {
|
|
68069
|
+
file_read: "read",
|
|
68070
|
+
file_edit: "edited",
|
|
68071
|
+
file_write: "wrote",
|
|
68072
|
+
patch_apply: "edited",
|
|
68073
|
+
notebook_edit: "edited"
|
|
68074
|
+
};
|
|
68075
|
+
const seen = new Set;
|
|
68076
|
+
const refs = [];
|
|
68077
|
+
for (const call2 of toolCalls) {
|
|
68078
|
+
const verb = verbs[canonicalToolName(call2.tool)];
|
|
68079
|
+
if (!verb)
|
|
68080
|
+
continue;
|
|
68081
|
+
const args2 = call2.args ?? {};
|
|
68082
|
+
const path = [args2.path, args2.file, args2.filePath, args2.notebookPath].find((value) => typeof value === "string" && value.trim());
|
|
68083
|
+
if (!path)
|
|
68084
|
+
continue;
|
|
68085
|
+
const line = `${verb} ${path.replace(/^\/workspace\//, "").replace(/^\/worktrees\/[^/]+\//, "")}`;
|
|
68086
|
+
if (!seen.has(line)) {
|
|
68087
|
+
seen.add(line);
|
|
68088
|
+
refs.push(line);
|
|
68089
|
+
}
|
|
68090
|
+
}
|
|
68091
|
+
return refs.slice(-12);
|
|
68092
|
+
}
|
|
67213
68093
|
function Transcript(props = {}) {
|
|
67214
68094
|
const tui = useTuiStore();
|
|
67215
68095
|
const dims = useTuiDimensions();
|
|
@@ -67226,12 +68106,16 @@ function Transcript(props = {}) {
|
|
|
67226
68106
|
return renderedTranscriptRows;
|
|
67227
68107
|
const boundary = tui.store.snapshot.compactionBoundary;
|
|
67228
68108
|
const summary = boundary ? formatCompactSummary(boundary.summary) : "";
|
|
68109
|
+
const references = boundary ? compactReferences(tui.store.snapshot.toolCalls) : [];
|
|
67229
68110
|
const compactRow = boundary ? [{
|
|
67230
68111
|
kind: "compaction",
|
|
67231
68112
|
id: boundary.id,
|
|
67232
68113
|
text: boundary.preCompactTokens !== undefined && boundary.postCompactTokens !== undefined ? `${boundary.preCompactTokens} \u2192 ${boundary.postCompactTokens} tokens` : "",
|
|
67233
68114
|
...summary ? {
|
|
67234
68115
|
summary
|
|
68116
|
+
} : {},
|
|
68117
|
+
...references.length ? {
|
|
68118
|
+
references
|
|
67235
68119
|
} : {}
|
|
67236
68120
|
}] : [];
|
|
67237
68121
|
renderedTranscriptRows = [...compactRow, ...tui.timelineRows()];
|
|
@@ -67586,6 +68470,7 @@ var init_transcript = __esm(() => {
|
|
|
67586
68470
|
init_branding();
|
|
67587
68471
|
init_terminal();
|
|
67588
68472
|
init_tool_activity();
|
|
68473
|
+
init_tool_names();
|
|
67589
68474
|
});
|
|
67590
68475
|
|
|
67591
68476
|
// src/agent-tui/surfaces/center-surface.tsx
|
|
@@ -70394,6 +71279,10 @@ function bottomPaneSurface(input) {
|
|
|
70394
71279
|
return "email_account_removal";
|
|
70395
71280
|
if (input.hasEmailAccountWizard)
|
|
70396
71281
|
return "email_account_wizard";
|
|
71282
|
+
if (input.hasLaneRemoval)
|
|
71283
|
+
return "lane_removal";
|
|
71284
|
+
if (input.hasLaneWizard)
|
|
71285
|
+
return "lane_wizard";
|
|
70397
71286
|
if (input.hasRequestUserInput)
|
|
70398
71287
|
return "user_input";
|
|
70399
71288
|
return bottomPaneSlot(input);
|
|
@@ -70839,22 +71728,33 @@ function StatusIndicator(props) {
|
|
|
70839
71728
|
const glyph = () => SPINNER_FRAMES[(props.spinnerFrame ?? 0) % SPINNER_FRAMES.length];
|
|
70840
71729
|
const text2 = () => {
|
|
70841
71730
|
if (props.activity) {
|
|
70842
|
-
const value2 = dims().width >= 56 ? `${
|
|
70843
|
-
return truncateLine2(value2.toLowerCase(), Math.max(1, dims().width));
|
|
71731
|
+
const value2 = dims().width >= 56 ? `${props.activity} (${fmtElapsed(props.elapsed)}${detail()} \u2022 esc to interrupt)` : `${props.activity} ${fmtElapsed(props.elapsed)} \xB7 esc interrupt`;
|
|
71732
|
+
return truncateLine2(value2.toLowerCase(), Math.max(1, dims().width - 2));
|
|
70844
71733
|
}
|
|
70845
71734
|
const value = tui.store.ui.statusDetail;
|
|
70846
71735
|
return truncateLine2((value && value !== "working" && !isFooterStatusDetail(value) ? `\u2022 ${value}` : "").toLowerCase(), Math.max(1, dims().width));
|
|
70847
71736
|
};
|
|
70848
71737
|
return (() => {
|
|
70849
|
-
var _el$ = createElement("box"), _el$
|
|
70850
|
-
insertNode(_el$, _el$
|
|
71738
|
+
var _el$ = createElement("box"), _el$3 = createElement("text");
|
|
71739
|
+
insertNode(_el$, _el$3);
|
|
70851
71740
|
setProp(_el$, "style", {
|
|
70852
71741
|
flexDirection: "row",
|
|
70853
71742
|
flexShrink: 0,
|
|
70854
71743
|
paddingTop: 1
|
|
70855
71744
|
});
|
|
70856
|
-
insert(_el
|
|
70857
|
-
|
|
71745
|
+
insert(_el$, createComponent2(Show, {
|
|
71746
|
+
get when() {
|
|
71747
|
+
return props.activity;
|
|
71748
|
+
},
|
|
71749
|
+
get children() {
|
|
71750
|
+
var _el$2 = createElement("text");
|
|
71751
|
+
insert(_el$2, () => `${glyph()} `);
|
|
71752
|
+
effect((_$p) => setProp(_el$2, "fg", COLOR.agent, _$p));
|
|
71753
|
+
return _el$2;
|
|
71754
|
+
}
|
|
71755
|
+
}), _el$3);
|
|
71756
|
+
insert(_el$3, text2);
|
|
71757
|
+
effect((_$p) => setProp(_el$3, "fg", COLOR.text, _$p));
|
|
70858
71758
|
return _el$;
|
|
70859
71759
|
})();
|
|
70860
71760
|
}
|
|
@@ -70865,6 +71765,8 @@ var init_status_indicator = __esm(() => {
|
|
|
70865
71765
|
init_solid2();
|
|
70866
71766
|
init_solid2();
|
|
70867
71767
|
init_solid2();
|
|
71768
|
+
init_solid2();
|
|
71769
|
+
init_solid();
|
|
70868
71770
|
init_store4();
|
|
70869
71771
|
init_renderers2();
|
|
70870
71772
|
init_terminal();
|
|
@@ -71836,6 +72738,8 @@ function overlaySubtitle(frame) {
|
|
|
71836
72738
|
return "review security findings";
|
|
71837
72739
|
if (frame.kind === "memory")
|
|
71838
72740
|
return "inspect durable memory";
|
|
72741
|
+
if (frame.kind === "subagents")
|
|
72742
|
+
return "roles farai can delegate to";
|
|
71839
72743
|
return "";
|
|
71840
72744
|
}
|
|
71841
72745
|
function overlayHint(frame, matches, providers, mcpServers) {
|
|
@@ -71859,6 +72763,8 @@ function overlayHint(frame, matches, providers, mcpServers) {
|
|
|
71859
72763
|
return "ctrl+a add email \xB7 esc back";
|
|
71860
72764
|
return selected.persistent ? "ctrl+p primary \xB7 ctrl+s secondary \xB7 ctrl+e edit \xB7 ctrl+t test \xB7 ctrl+d remove \xB7 esc back" : "ctrl+p primary \xB7 ctrl+s secondary \xB7 esc back";
|
|
71861
72765
|
}
|
|
72766
|
+
if (frame.kind === "subagents")
|
|
72767
|
+
return "ctrl+a add \xB7 ctrl+e edit \xB7 ctrl+d delete \xB7 esc close";
|
|
71862
72768
|
if (frame.kind !== "model")
|
|
71863
72769
|
return "press enter to confirm or esc to go back";
|
|
71864
72770
|
if (selected?.kind === "model_action")
|
|
@@ -73911,6 +74817,595 @@ var init_email_account_wizard = __esm(() => {
|
|
|
73911
74817
|
TEXT_FIELDS = ["label", "address", "username", "endpoint", "clientId", "clientSecret", "credential"];
|
|
73912
74818
|
});
|
|
73913
74819
|
|
|
74820
|
+
// src/agent-tui/bottom-pane/multi-select-rows.tsx
|
|
74821
|
+
function MultiSelectRows(props) {
|
|
74822
|
+
const dims = useTuiDimensions();
|
|
74823
|
+
const limit = () => Math.max(1, Math.min(6, props.visibleLimit ?? 6));
|
|
74824
|
+
const window = createMemo(() => {
|
|
74825
|
+
const cursor = Math.max(0, Math.min(props.cursor, props.items.length - 1));
|
|
74826
|
+
const start = Math.max(0, Math.min(cursor - Math.floor(limit() / 2), Math.max(0, props.items.length - limit())));
|
|
74827
|
+
return props.items.slice(start, start + limit()).map((item, index) => ({
|
|
74828
|
+
item,
|
|
74829
|
+
index: start + index
|
|
74830
|
+
}));
|
|
74831
|
+
});
|
|
74832
|
+
return (() => {
|
|
74833
|
+
var _el$ = createElement("box");
|
|
74834
|
+
setProp(_el$, "style", {
|
|
74835
|
+
flexDirection: "column"
|
|
74836
|
+
});
|
|
74837
|
+
insert(_el$, createComponent2(For, {
|
|
74838
|
+
get each() {
|
|
74839
|
+
return window();
|
|
74840
|
+
},
|
|
74841
|
+
get fallback() {
|
|
74842
|
+
return (() => {
|
|
74843
|
+
var _el$2 = createElement("text");
|
|
74844
|
+
insertNode(_el$2, createTextNode(` no matching tools`));
|
|
74845
|
+
effect((_$p) => setProp(_el$2, "fg", COLOR.dim, _$p));
|
|
74846
|
+
return _el$2;
|
|
74847
|
+
})();
|
|
74848
|
+
},
|
|
74849
|
+
children: (entry) => {
|
|
74850
|
+
const active = () => entry.index === Math.max(0, Math.min(props.cursor, props.items.length - 1));
|
|
74851
|
+
const checked = () => props.selected(entry.item);
|
|
74852
|
+
return (() => {
|
|
74853
|
+
var _el$4 = createElement("box"), _el$5 = createElement("text"), _el$6 = createElement("text"), _el$7 = createElement("text");
|
|
74854
|
+
insertNode(_el$4, _el$5);
|
|
74855
|
+
insertNode(_el$4, _el$6);
|
|
74856
|
+
insertNode(_el$4, _el$7);
|
|
74857
|
+
setProp(_el$4, "style", {
|
|
74858
|
+
flexDirection: "row"
|
|
74859
|
+
});
|
|
74860
|
+
setProp(_el$5, "selectable", false);
|
|
74861
|
+
insert(_el$5, () => active() ? "\u203A " : " ");
|
|
74862
|
+
setProp(_el$6, "selectable", false);
|
|
74863
|
+
insert(_el$6, () => checked() ? "\u25C9 " : "\u25CB ");
|
|
74864
|
+
setProp(_el$7, "selectable", false);
|
|
74865
|
+
insert(_el$7, () => truncateLine2(entry.item, Math.max(1, dims().width - 8)));
|
|
74866
|
+
effect((_p$) => {
|
|
74867
|
+
var _v$ = active() ? COLOR.accent : COLOR.dim, _v$2 = checked() ? COLOR.success : COLOR.dim, _v$3 = active() ? COLOR.text : checked() ? COLOR.text : COLOR.dim;
|
|
74868
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$5, "fg", _v$, _p$.e));
|
|
74869
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$6, "fg", _v$2, _p$.t));
|
|
74870
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$7, "fg", _v$3, _p$.a));
|
|
74871
|
+
return _p$;
|
|
74872
|
+
}, {
|
|
74873
|
+
e: undefined,
|
|
74874
|
+
t: undefined,
|
|
74875
|
+
a: undefined
|
|
74876
|
+
});
|
|
74877
|
+
return _el$4;
|
|
74878
|
+
})();
|
|
74879
|
+
}
|
|
74880
|
+
}));
|
|
74881
|
+
return _el$;
|
|
74882
|
+
})();
|
|
74883
|
+
}
|
|
74884
|
+
var init_multi_select_rows = __esm(() => {
|
|
74885
|
+
init_solid2();
|
|
74886
|
+
init_solid2();
|
|
74887
|
+
init_solid2();
|
|
74888
|
+
init_solid2();
|
|
74889
|
+
init_solid2();
|
|
74890
|
+
init_solid2();
|
|
74891
|
+
init_solid2();
|
|
74892
|
+
init_solid2();
|
|
74893
|
+
init_solid();
|
|
74894
|
+
init_theme();
|
|
74895
|
+
init_renderers2();
|
|
74896
|
+
init_terminal();
|
|
74897
|
+
});
|
|
74898
|
+
|
|
74899
|
+
// src/agent-tui/bottom-pane/lane-wizard.tsx
|
|
74900
|
+
function LaneWizard() {
|
|
74901
|
+
const tui = useTuiStore();
|
|
74902
|
+
const dims = useTuiDimensions();
|
|
74903
|
+
let inputRef;
|
|
74904
|
+
let inputField;
|
|
74905
|
+
let promptRef;
|
|
74906
|
+
const wizard = () => tui.store.ui.laneWizard;
|
|
74907
|
+
const value = () => {
|
|
74908
|
+
const field2 = wizard().field;
|
|
74909
|
+
if (field2 === "id")
|
|
74910
|
+
return wizard().id;
|
|
74911
|
+
if (field2 === "description")
|
|
74912
|
+
return wizard().description;
|
|
74913
|
+
if (field2 === "model")
|
|
74914
|
+
return wizard().model;
|
|
74915
|
+
return "";
|
|
74916
|
+
};
|
|
74917
|
+
const placeholder2 = () => {
|
|
74918
|
+
const field2 = wizard().field;
|
|
74919
|
+
if (field2 === "id")
|
|
74920
|
+
return "osint";
|
|
74921
|
+
if (field2 === "description")
|
|
74922
|
+
return "short role summary shown when picking a lane";
|
|
74923
|
+
if (field2 === "model")
|
|
74924
|
+
return "optional model id \xB7 empty inherits parent";
|
|
74925
|
+
return "";
|
|
74926
|
+
};
|
|
74927
|
+
const title = () => wizard().mode === "add" ? "add lane" : `edit ${wizard().id}`;
|
|
74928
|
+
const step = () => `${laneWizardStep(wizard().field)}/${laneWizardStepCount()}`;
|
|
74929
|
+
const header = () => fitTerminalPair(title(), step(), Math.max(1, dims().width - 4), 4, 1);
|
|
74930
|
+
const isTextField = () => TEXT_FIELDS2.includes(wizard().field);
|
|
74931
|
+
const visibleTools = () => filteredToolNames(tui.store.ui.toolNames, wizard().toolFilter);
|
|
74932
|
+
const bodyHeight = () => wizard().field === "prompt" ? inputFieldHeight(dims().height) + 6 : isTextField() ? inputFieldHeight(dims().height) + 4 : 9;
|
|
74933
|
+
const wizardHeight = () => bodyHeight() + 3;
|
|
74934
|
+
const status = () => wizard().error ?? tui.store.ui.lastError ?? (wizard().busy ? "saving lane\u2026" : "");
|
|
74935
|
+
const statusColor2 = () => wizard().error || tui.store.ui.lastError ? COLOR.error : COLOR.accent;
|
|
74936
|
+
createEffect(() => {
|
|
74937
|
+
const field2 = wizard().field;
|
|
74938
|
+
const activeText = isTextField() && !wizard().busy;
|
|
74939
|
+
if (activeText) {
|
|
74940
|
+
if (inputRef && inputField === field2 && inputRef.value !== value())
|
|
74941
|
+
inputRef.value = value();
|
|
74942
|
+
if (inputField === field2) {
|
|
74943
|
+
try {
|
|
74944
|
+
inputRef?.focus();
|
|
74945
|
+
} catch {}
|
|
74946
|
+
}
|
|
74947
|
+
} else {
|
|
74948
|
+
try {
|
|
74949
|
+
inputRef?.blur();
|
|
74950
|
+
} catch {}
|
|
74951
|
+
}
|
|
74952
|
+
if (field2 === "prompt" && !wizard().busy) {
|
|
74953
|
+
try {
|
|
74954
|
+
promptRef?.focus();
|
|
74955
|
+
} catch {}
|
|
74956
|
+
} else {
|
|
74957
|
+
try {
|
|
74958
|
+
promptRef?.blur();
|
|
74959
|
+
} catch {}
|
|
74960
|
+
}
|
|
74961
|
+
});
|
|
74962
|
+
onCleanup(() => {
|
|
74963
|
+
try {
|
|
74964
|
+
inputRef?.blur();
|
|
74965
|
+
} catch {}
|
|
74966
|
+
try {
|
|
74967
|
+
promptRef?.blur();
|
|
74968
|
+
} catch {}
|
|
74969
|
+
inputRef = undefined;
|
|
74970
|
+
inputField = undefined;
|
|
74971
|
+
promptRef = undefined;
|
|
74972
|
+
});
|
|
74973
|
+
return (() => {
|
|
74974
|
+
var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createElement("text"), _el$5 = createElement("box"), _el$9 = createElement("box"), _el$0 = createElement("text"), _el$1 = createElement("box"), _el$10 = createElement("text");
|
|
74975
|
+
insertNode(_el$, _el$2);
|
|
74976
|
+
insertNode(_el$, _el$5);
|
|
74977
|
+
insertNode(_el$, _el$9);
|
|
74978
|
+
insertNode(_el$, _el$1);
|
|
74979
|
+
setProp(_el$, "id", "lane-wizard");
|
|
74980
|
+
insertNode(_el$2, _el$3);
|
|
74981
|
+
insertNode(_el$2, _el$4);
|
|
74982
|
+
setProp(_el$2, "style", {
|
|
74983
|
+
height: 1,
|
|
74984
|
+
flexDirection: "row",
|
|
74985
|
+
justifyContent: "space-between",
|
|
74986
|
+
paddingLeft: 2,
|
|
74987
|
+
paddingRight: 2
|
|
74988
|
+
});
|
|
74989
|
+
insert(_el$3, () => header().left);
|
|
74990
|
+
insert(_el$4, () => header().right);
|
|
74991
|
+
insert(_el$5, createComponent2(Show, {
|
|
74992
|
+
get when() {
|
|
74993
|
+
return wizard().field === "tools";
|
|
74994
|
+
},
|
|
74995
|
+
get fallback() {
|
|
74996
|
+
return createComponent2(Show, {
|
|
74997
|
+
get when() {
|
|
74998
|
+
return wizard().field === "prompt";
|
|
74999
|
+
},
|
|
75000
|
+
get fallback() {
|
|
75001
|
+
return createComponent2(Show, {
|
|
75002
|
+
get when() {
|
|
75003
|
+
return wizard().field === "review";
|
|
75004
|
+
},
|
|
75005
|
+
get fallback() {
|
|
75006
|
+
return createComponent2(Show, {
|
|
75007
|
+
get when() {
|
|
75008
|
+
return wizard().field;
|
|
75009
|
+
},
|
|
75010
|
+
keyed: true,
|
|
75011
|
+
children: (field2) => (() => {
|
|
75012
|
+
var _el$16 = createElement("box"), _el$17 = createElement("text");
|
|
75013
|
+
insertNode(_el$16, _el$17);
|
|
75014
|
+
setProp(_el$16, "style", {
|
|
75015
|
+
flexDirection: "column",
|
|
75016
|
+
paddingTop: 1,
|
|
75017
|
+
paddingLeft: 2,
|
|
75018
|
+
paddingRight: 1
|
|
75019
|
+
});
|
|
75020
|
+
insert(_el$17, () => truncateLine2(fieldLabel3(field2), Math.max(1, dims().width - 3)));
|
|
75021
|
+
insert(_el$16, createComponent2(InputField, {
|
|
75022
|
+
marginTop: 1,
|
|
75023
|
+
get children() {
|
|
75024
|
+
return [createComponent2(InputFieldPrompt, {}), (() => {
|
|
75025
|
+
var _el$18 = createElement("input");
|
|
75026
|
+
use((node) => {
|
|
75027
|
+
inputRef = node;
|
|
75028
|
+
inputField = field2;
|
|
75029
|
+
if (node.value !== value())
|
|
75030
|
+
node.value = value();
|
|
75031
|
+
node.focus();
|
|
75032
|
+
}, _el$18);
|
|
75033
|
+
setProp(_el$18, "id", "lane-wizard-input");
|
|
75034
|
+
setProp(_el$18, "onInput", (next) => updateField2(tui, field2, next));
|
|
75035
|
+
effect((_p$) => {
|
|
75036
|
+
var _v$12 = value(), _v$13 = placeholder2(), _v$14 = COLOR.dim, _v$15 = COLOR.text, _v$16 = COLOR.text, _v$17 = COLOR.accent, _v$18 = {
|
|
75037
|
+
flexGrow: 1,
|
|
75038
|
+
backgroundColor: COLOR.panelActive
|
|
75039
|
+
};
|
|
75040
|
+
_v$12 !== _p$.e && (_p$.e = setProp(_el$18, "value", _v$12, _p$.e));
|
|
75041
|
+
_v$13 !== _p$.t && (_p$.t = setProp(_el$18, "placeholder", _v$13, _p$.t));
|
|
75042
|
+
_v$14 !== _p$.a && (_p$.a = setProp(_el$18, "placeholderColor", _v$14, _p$.a));
|
|
75043
|
+
_v$15 !== _p$.o && (_p$.o = setProp(_el$18, "textColor", _v$15, _p$.o));
|
|
75044
|
+
_v$16 !== _p$.i && (_p$.i = setProp(_el$18, "focusedTextColor", _v$16, _p$.i));
|
|
75045
|
+
_v$17 !== _p$.n && (_p$.n = setProp(_el$18, "cursorColor", _v$17, _p$.n));
|
|
75046
|
+
_v$18 !== _p$.s && (_p$.s = setProp(_el$18, "style", _v$18, _p$.s));
|
|
75047
|
+
return _p$;
|
|
75048
|
+
}, {
|
|
75049
|
+
e: undefined,
|
|
75050
|
+
t: undefined,
|
|
75051
|
+
a: undefined,
|
|
75052
|
+
o: undefined,
|
|
75053
|
+
i: undefined,
|
|
75054
|
+
n: undefined,
|
|
75055
|
+
s: undefined
|
|
75056
|
+
});
|
|
75057
|
+
return _el$18;
|
|
75058
|
+
})()];
|
|
75059
|
+
}
|
|
75060
|
+
}), null);
|
|
75061
|
+
effect((_$p) => setProp(_el$17, "fg", COLOR.dim, _$p));
|
|
75062
|
+
return _el$16;
|
|
75063
|
+
})()
|
|
75064
|
+
});
|
|
75065
|
+
},
|
|
75066
|
+
get children() {
|
|
75067
|
+
return createComponent2(LaneReview, {});
|
|
75068
|
+
}
|
|
75069
|
+
});
|
|
75070
|
+
},
|
|
75071
|
+
get children() {
|
|
75072
|
+
var _el$11 = createElement("box"), _el$12 = createElement("text"), _el$14 = createElement("box"), _el$15 = createElement("textarea");
|
|
75073
|
+
insertNode(_el$11, _el$12);
|
|
75074
|
+
insertNode(_el$11, _el$14);
|
|
75075
|
+
setProp(_el$11, "style", {
|
|
75076
|
+
flexDirection: "column",
|
|
75077
|
+
paddingTop: 1,
|
|
75078
|
+
paddingLeft: 2,
|
|
75079
|
+
paddingRight: 1
|
|
75080
|
+
});
|
|
75081
|
+
insertNode(_el$12, createTextNode(`role prompt \xB7 optional \xB7 injected into the subagent`));
|
|
75082
|
+
insertNode(_el$14, _el$15);
|
|
75083
|
+
use((node) => {
|
|
75084
|
+
promptRef = node;
|
|
75085
|
+
try {
|
|
75086
|
+
node.setText(wizard().prompt);
|
|
75087
|
+
} catch {}
|
|
75088
|
+
node.focus();
|
|
75089
|
+
}, _el$15);
|
|
75090
|
+
setProp(_el$15, "id", "lane-prompt-input");
|
|
75091
|
+
setProp(_el$15, "placeholder", "describe how this role should work");
|
|
75092
|
+
setProp(_el$15, "wrapMode", "word");
|
|
75093
|
+
setProp(_el$15, "onContentChange", () => {
|
|
75094
|
+
tui.actions.laneWizardPatch({
|
|
75095
|
+
prompt: promptRef?.plainText ?? "",
|
|
75096
|
+
error: undefined
|
|
75097
|
+
});
|
|
75098
|
+
});
|
|
75099
|
+
effect((_p$) => {
|
|
75100
|
+
var _v$7 = COLOR.dim, _v$8 = {
|
|
75101
|
+
flexDirection: "row",
|
|
75102
|
+
marginTop: 1,
|
|
75103
|
+
paddingTop: 1,
|
|
75104
|
+
paddingBottom: 1,
|
|
75105
|
+
paddingLeft: 1,
|
|
75106
|
+
paddingRight: 1,
|
|
75107
|
+
backgroundColor: COLOR.panelActive
|
|
75108
|
+
}, _v$9 = COLOR.dim, _v$0 = COLOR.text, _v$1 = COLOR.text, _v$10 = COLOR.accent, _v$11 = {
|
|
75109
|
+
height: Math.max(3, inputFieldHeight(dims().height)),
|
|
75110
|
+
flexGrow: 1,
|
|
75111
|
+
backgroundColor: "transparent"
|
|
75112
|
+
};
|
|
75113
|
+
_v$7 !== _p$.e && (_p$.e = setProp(_el$12, "fg", _v$7, _p$.e));
|
|
75114
|
+
_v$8 !== _p$.t && (_p$.t = setProp(_el$14, "style", _v$8, _p$.t));
|
|
75115
|
+
_v$9 !== _p$.a && (_p$.a = setProp(_el$15, "placeholderColor", _v$9, _p$.a));
|
|
75116
|
+
_v$0 !== _p$.o && (_p$.o = setProp(_el$15, "textColor", _v$0, _p$.o));
|
|
75117
|
+
_v$1 !== _p$.i && (_p$.i = setProp(_el$15, "focusedTextColor", _v$1, _p$.i));
|
|
75118
|
+
_v$10 !== _p$.n && (_p$.n = setProp(_el$15, "cursorColor", _v$10, _p$.n));
|
|
75119
|
+
_v$11 !== _p$.s && (_p$.s = setProp(_el$15, "style", _v$11, _p$.s));
|
|
75120
|
+
return _p$;
|
|
75121
|
+
}, {
|
|
75122
|
+
e: undefined,
|
|
75123
|
+
t: undefined,
|
|
75124
|
+
a: undefined,
|
|
75125
|
+
o: undefined,
|
|
75126
|
+
i: undefined,
|
|
75127
|
+
n: undefined,
|
|
75128
|
+
s: undefined
|
|
75129
|
+
});
|
|
75130
|
+
return _el$11;
|
|
75131
|
+
}
|
|
75132
|
+
});
|
|
75133
|
+
},
|
|
75134
|
+
get children() {
|
|
75135
|
+
var _el$6 = createElement("box"), _el$7 = createElement("text"), _el$8 = createElement("box");
|
|
75136
|
+
insertNode(_el$6, _el$7);
|
|
75137
|
+
insertNode(_el$6, _el$8);
|
|
75138
|
+
setProp(_el$6, "style", {
|
|
75139
|
+
flexDirection: "column",
|
|
75140
|
+
paddingTop: 1,
|
|
75141
|
+
paddingLeft: 2,
|
|
75142
|
+
paddingRight: 1
|
|
75143
|
+
});
|
|
75144
|
+
insert(_el$7, () => truncateLine2(`tools \xB7 ${wizard().tools.length} selected \xB7 omit to inherit${wizard().toolFilter ? ` \xB7 filter: ${wizard().toolFilter}` : ""}`, Math.max(1, dims().width - 3)));
|
|
75145
|
+
setProp(_el$8, "style", {
|
|
75146
|
+
marginTop: 1
|
|
75147
|
+
});
|
|
75148
|
+
insert(_el$8, createComponent2(MultiSelectRows, {
|
|
75149
|
+
get items() {
|
|
75150
|
+
return visibleTools();
|
|
75151
|
+
},
|
|
75152
|
+
selected: (name) => wizard().tools.includes(name),
|
|
75153
|
+
get cursor() {
|
|
75154
|
+
return wizard().toolCursor;
|
|
75155
|
+
}
|
|
75156
|
+
}));
|
|
75157
|
+
effect((_$p) => setProp(_el$7, "fg", COLOR.dim, _$p));
|
|
75158
|
+
return _el$6;
|
|
75159
|
+
}
|
|
75160
|
+
}));
|
|
75161
|
+
insertNode(_el$9, _el$0);
|
|
75162
|
+
setProp(_el$9, "style", {
|
|
75163
|
+
height: 1,
|
|
75164
|
+
paddingLeft: 2,
|
|
75165
|
+
paddingRight: 1
|
|
75166
|
+
});
|
|
75167
|
+
insert(_el$0, () => truncateLine2(status(), Math.max(1, dims().width - 3)));
|
|
75168
|
+
insertNode(_el$1, _el$10);
|
|
75169
|
+
setProp(_el$1, "style", {
|
|
75170
|
+
height: 1,
|
|
75171
|
+
paddingLeft: 2,
|
|
75172
|
+
paddingRight: 1
|
|
75173
|
+
});
|
|
75174
|
+
insert(_el$10, () => truncateLine2(wizardHint3(wizard().field), Math.max(1, dims().width - 3)));
|
|
75175
|
+
effect((_p$) => {
|
|
75176
|
+
var _v$ = {
|
|
75177
|
+
height: wizardHeight(),
|
|
75178
|
+
flexShrink: 0,
|
|
75179
|
+
flexDirection: "column",
|
|
75180
|
+
overflow: "hidden"
|
|
75181
|
+
}, _v$2 = COLOR.text, _v$3 = COLOR.dim, _v$4 = {
|
|
75182
|
+
height: bodyHeight(),
|
|
75183
|
+
flexShrink: 0,
|
|
75184
|
+
flexDirection: "column",
|
|
75185
|
+
overflow: "hidden"
|
|
75186
|
+
}, _v$5 = statusColor2(), _v$6 = COLOR.dim;
|
|
75187
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$, "style", _v$, _p$.e));
|
|
75188
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$3, "fg", _v$2, _p$.t));
|
|
75189
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$4, "fg", _v$3, _p$.a));
|
|
75190
|
+
_v$4 !== _p$.o && (_p$.o = setProp(_el$5, "style", _v$4, _p$.o));
|
|
75191
|
+
_v$5 !== _p$.i && (_p$.i = setProp(_el$0, "fg", _v$5, _p$.i));
|
|
75192
|
+
_v$6 !== _p$.n && (_p$.n = setProp(_el$10, "fg", _v$6, _p$.n));
|
|
75193
|
+
return _p$;
|
|
75194
|
+
}, {
|
|
75195
|
+
e: undefined,
|
|
75196
|
+
t: undefined,
|
|
75197
|
+
a: undefined,
|
|
75198
|
+
o: undefined,
|
|
75199
|
+
i: undefined,
|
|
75200
|
+
n: undefined
|
|
75201
|
+
});
|
|
75202
|
+
return _el$;
|
|
75203
|
+
})();
|
|
75204
|
+
}
|
|
75205
|
+
function LaneReview() {
|
|
75206
|
+
const tui = useTuiStore();
|
|
75207
|
+
const dims = useTuiDimensions();
|
|
75208
|
+
const wizard = () => tui.store.ui.laneWizard;
|
|
75209
|
+
const width = () => Math.max(1, dims().width - 2);
|
|
75210
|
+
return (() => {
|
|
75211
|
+
var _el$19 = createElement("box"), _el$20 = createElement("text"), _el$21 = createElement("text"), _el$22 = createElement("text"), _el$23 = createElement("text"), _el$24 = createElement("text");
|
|
75212
|
+
insertNode(_el$19, _el$20);
|
|
75213
|
+
insertNode(_el$19, _el$21);
|
|
75214
|
+
insertNode(_el$19, _el$22);
|
|
75215
|
+
insertNode(_el$19, _el$23);
|
|
75216
|
+
insertNode(_el$19, _el$24);
|
|
75217
|
+
setProp(_el$19, "style", {
|
|
75218
|
+
flexDirection: "column",
|
|
75219
|
+
paddingTop: 1,
|
|
75220
|
+
paddingLeft: 2
|
|
75221
|
+
});
|
|
75222
|
+
insert(_el$20, () => truncateLine2(wizard().id || "unnamed lane", width()));
|
|
75223
|
+
insert(_el$21, () => truncateLine2(wizard().description || "no description", width()));
|
|
75224
|
+
insert(_el$22, () => truncateLine2(wizard().tools.length ? `tools: ${wizard().tools.join(", ")}` : "tools: inherit parent scope", width()));
|
|
75225
|
+
insert(_el$23, () => truncateLine2(wizard().model ? `model: ${wizard().model}` : "model: inherit parent", width()));
|
|
75226
|
+
insert(_el$24, () => truncateLine2(wizard().prompt ? `prompt: ${wizard().prompt.split(`
|
|
75227
|
+
`)[0]}` : "prompt: none", width()));
|
|
75228
|
+
effect((_p$) => {
|
|
75229
|
+
var _v$19 = COLOR.text, _v$20 = COLOR.dim, _v$21 = COLOR.dim, _v$22 = COLOR.dim, _v$23 = COLOR.dim;
|
|
75230
|
+
_v$19 !== _p$.e && (_p$.e = setProp(_el$20, "fg", _v$19, _p$.e));
|
|
75231
|
+
_v$20 !== _p$.t && (_p$.t = setProp(_el$21, "fg", _v$20, _p$.t));
|
|
75232
|
+
_v$21 !== _p$.a && (_p$.a = setProp(_el$22, "fg", _v$21, _p$.a));
|
|
75233
|
+
_v$22 !== _p$.o && (_p$.o = setProp(_el$23, "fg", _v$22, _p$.o));
|
|
75234
|
+
_v$23 !== _p$.i && (_p$.i = setProp(_el$24, "fg", _v$23, _p$.i));
|
|
75235
|
+
return _p$;
|
|
75236
|
+
}, {
|
|
75237
|
+
e: undefined,
|
|
75238
|
+
t: undefined,
|
|
75239
|
+
a: undefined,
|
|
75240
|
+
o: undefined,
|
|
75241
|
+
i: undefined
|
|
75242
|
+
});
|
|
75243
|
+
return _el$19;
|
|
75244
|
+
})();
|
|
75245
|
+
}
|
|
75246
|
+
function updateField2(tui, field2, value) {
|
|
75247
|
+
tui.actions.errorSet(undefined);
|
|
75248
|
+
if (field2 === "id")
|
|
75249
|
+
tui.actions.laneWizardPatch({
|
|
75250
|
+
id: value,
|
|
75251
|
+
error: undefined
|
|
75252
|
+
});
|
|
75253
|
+
if (field2 === "description")
|
|
75254
|
+
tui.actions.laneWizardPatch({
|
|
75255
|
+
description: value,
|
|
75256
|
+
error: undefined
|
|
75257
|
+
});
|
|
75258
|
+
if (field2 === "model")
|
|
75259
|
+
tui.actions.laneWizardPatch({
|
|
75260
|
+
model: value,
|
|
75261
|
+
error: undefined
|
|
75262
|
+
});
|
|
75263
|
+
}
|
|
75264
|
+
function fieldLabel3(field2) {
|
|
75265
|
+
if (field2 === "id")
|
|
75266
|
+
return "lane id";
|
|
75267
|
+
if (field2 === "description")
|
|
75268
|
+
return "description \xB7 optional";
|
|
75269
|
+
if (field2 === "model")
|
|
75270
|
+
return "model \xB7 optional \xB7 empty inherits parent";
|
|
75271
|
+
return field2;
|
|
75272
|
+
}
|
|
75273
|
+
function wizardHint3(field2) {
|
|
75274
|
+
if (field2 === "prompt")
|
|
75275
|
+
return "type \xB7 enter newline \xB7 ctrl+s continue \xB7 esc back";
|
|
75276
|
+
if (field2 === "tools")
|
|
75277
|
+
return "\u2191\u2193 move \xB7 space toggle \xB7 ctrl+a all \xB7 type filter \xB7 enter continue \xB7 esc back";
|
|
75278
|
+
if (field2 === "review")
|
|
75279
|
+
return "enter save \xB7 esc back";
|
|
75280
|
+
return "enter continue \xB7 esc back";
|
|
75281
|
+
}
|
|
75282
|
+
var TEXT_FIELDS2;
|
|
75283
|
+
var init_lane_wizard = __esm(() => {
|
|
75284
|
+
init_solid2();
|
|
75285
|
+
init_solid2();
|
|
75286
|
+
init_solid2();
|
|
75287
|
+
init_solid2();
|
|
75288
|
+
init_solid2();
|
|
75289
|
+
init_solid2();
|
|
75290
|
+
init_solid2();
|
|
75291
|
+
init_solid2();
|
|
75292
|
+
init_solid();
|
|
75293
|
+
init_store4();
|
|
75294
|
+
init_lane_state();
|
|
75295
|
+
init_theme();
|
|
75296
|
+
init_renderers2();
|
|
75297
|
+
init_terminal_text();
|
|
75298
|
+
init_terminal();
|
|
75299
|
+
init_input_field();
|
|
75300
|
+
init_multi_select_rows();
|
|
75301
|
+
TEXT_FIELDS2 = ["id", "description", "model"];
|
|
75302
|
+
});
|
|
75303
|
+
|
|
75304
|
+
// src/agent-tui/bottom-pane/lane-removal.tsx
|
|
75305
|
+
function LaneRemoval() {
|
|
75306
|
+
const tui = useTuiStore();
|
|
75307
|
+
const dims = useTuiDimensions();
|
|
75308
|
+
const state = () => tui.store.ui.laneRemoval;
|
|
75309
|
+
const lane = () => state().lane;
|
|
75310
|
+
const title = () => `remove ${lane().id}`;
|
|
75311
|
+
const descriptionColumn2 = () => selectionDescriptionColumn([{
|
|
75312
|
+
title: title()
|
|
75313
|
+
}], dims().width);
|
|
75314
|
+
const header = () => fitTerminalPair("remove lane", lane().source, Math.max(1, dims().width - 4), 8, 1);
|
|
75315
|
+
const hint = () => state().busy ? `removing ${lane().id}\u2026` : state().error ? `error \xB7 ${state().error}` : "enter remove \xB7 esc cancel";
|
|
75316
|
+
return (() => {
|
|
75317
|
+
var _el$ = createElement("box"), _el$2 = createElement("box"), _el$3 = createElement("text"), _el$4 = createElement("text"), _el$5 = createElement("box"), _el$6 = createElement("text"), _el$7 = createElement("box");
|
|
75318
|
+
insertNode(_el$, _el$2);
|
|
75319
|
+
insertNode(_el$, _el$5);
|
|
75320
|
+
setProp(_el$, "id", "lane-removal");
|
|
75321
|
+
setProp(_el$, "style", {
|
|
75322
|
+
height: 8,
|
|
75323
|
+
flexShrink: 0,
|
|
75324
|
+
flexDirection: "column",
|
|
75325
|
+
overflow: "hidden"
|
|
75326
|
+
});
|
|
75327
|
+
insertNode(_el$2, _el$3);
|
|
75328
|
+
insertNode(_el$2, _el$4);
|
|
75329
|
+
setProp(_el$2, "style", {
|
|
75330
|
+
height: 1,
|
|
75331
|
+
flexDirection: "row",
|
|
75332
|
+
justifyContent: "space-between",
|
|
75333
|
+
paddingLeft: 2,
|
|
75334
|
+
paddingRight: 2
|
|
75335
|
+
});
|
|
75336
|
+
insert(_el$3, () => header().left);
|
|
75337
|
+
insert(_el$4, () => header().right);
|
|
75338
|
+
insertNode(_el$5, _el$6);
|
|
75339
|
+
insertNode(_el$5, _el$7);
|
|
75340
|
+
setProp(_el$5, "style", {
|
|
75341
|
+
height: 5,
|
|
75342
|
+
flexShrink: 0,
|
|
75343
|
+
flexDirection: "column",
|
|
75344
|
+
paddingTop: 1,
|
|
75345
|
+
overflow: "hidden"
|
|
75346
|
+
});
|
|
75347
|
+
insert(_el$6, () => ` ${truncateLine2(`remove custom lane ${lane().id}?`, Math.max(1, dims().width - 2))}`);
|
|
75348
|
+
setProp(_el$7, "style", {
|
|
75349
|
+
flexDirection: "column",
|
|
75350
|
+
marginTop: 1
|
|
75351
|
+
});
|
|
75352
|
+
insert(_el$7, createComponent2(SelectionRow, {
|
|
75353
|
+
get title() {
|
|
75354
|
+
return title();
|
|
75355
|
+
},
|
|
75356
|
+
description: "reverts to the builtin definition if one exists",
|
|
75357
|
+
selected: true,
|
|
75358
|
+
get disabled() {
|
|
75359
|
+
return state().busy;
|
|
75360
|
+
},
|
|
75361
|
+
get width() {
|
|
75362
|
+
return dims().width;
|
|
75363
|
+
},
|
|
75364
|
+
get descriptionColumn() {
|
|
75365
|
+
return descriptionColumn2();
|
|
75366
|
+
},
|
|
75367
|
+
get titleColor() {
|
|
75368
|
+
return COLOR.error;
|
|
75369
|
+
}
|
|
75370
|
+
}));
|
|
75371
|
+
insert(_el$, createComponent2(SelectionMenuHint, {
|
|
75372
|
+
get text() {
|
|
75373
|
+
return hint();
|
|
75374
|
+
},
|
|
75375
|
+
get color() {
|
|
75376
|
+
return memo2(() => !!state().error)() ? COLOR.error : undefined;
|
|
75377
|
+
}
|
|
75378
|
+
}), null);
|
|
75379
|
+
effect((_p$) => {
|
|
75380
|
+
var _v$ = COLOR.text, _v$2 = COLOR.dim, _v$3 = COLOR.accent;
|
|
75381
|
+
_v$ !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$, _p$.e));
|
|
75382
|
+
_v$2 !== _p$.t && (_p$.t = setProp(_el$4, "fg", _v$2, _p$.t));
|
|
75383
|
+
_v$3 !== _p$.a && (_p$.a = setProp(_el$6, "fg", _v$3, _p$.a));
|
|
75384
|
+
return _p$;
|
|
75385
|
+
}, {
|
|
75386
|
+
e: undefined,
|
|
75387
|
+
t: undefined,
|
|
75388
|
+
a: undefined
|
|
75389
|
+
});
|
|
75390
|
+
return _el$;
|
|
75391
|
+
})();
|
|
75392
|
+
}
|
|
75393
|
+
var init_lane_removal = __esm(() => {
|
|
75394
|
+
init_solid2();
|
|
75395
|
+
init_solid2();
|
|
75396
|
+
init_solid2();
|
|
75397
|
+
init_solid2();
|
|
75398
|
+
init_solid2();
|
|
75399
|
+
init_solid2();
|
|
75400
|
+
init_solid2();
|
|
75401
|
+
init_store4();
|
|
75402
|
+
init_selection_row();
|
|
75403
|
+
init_theme();
|
|
75404
|
+
init_renderers2();
|
|
75405
|
+
init_terminal_text();
|
|
75406
|
+
init_terminal();
|
|
75407
|
+
});
|
|
75408
|
+
|
|
73914
75409
|
// src/agent-tui/bottom-pane/email-account-removal.tsx
|
|
73915
75410
|
function EmailAccountRemoval() {
|
|
73916
75411
|
const tui = useTuiStore();
|
|
@@ -74066,6 +75561,8 @@ function BottomPane() {
|
|
|
74066
75561
|
hasMcpServerWizard: mcpServerWizardActive(),
|
|
74067
75562
|
hasEmailAccountRemoval: emailAccountRemovalActive(),
|
|
74068
75563
|
hasEmailAccountWizard: emailAccountWizardActive(),
|
|
75564
|
+
hasLaneRemoval: laneRemovalActive(),
|
|
75565
|
+
hasLaneWizard: laneWizardActive(),
|
|
74069
75566
|
hasRequestUserInput: inputRequestActive(),
|
|
74070
75567
|
hasListFrame: Boolean(listFrame()),
|
|
74071
75568
|
hasCenterFrame: Boolean(centerFrame()),
|
|
@@ -74077,6 +75574,8 @@ function BottomPane() {
|
|
|
74077
75574
|
const mcpServerRemovalActive = () => Boolean(tui.store.ui.mcpServerRemoval);
|
|
74078
75575
|
const emailAccountWizardActive = () => Boolean(tui.store.ui.emailAccountWizard);
|
|
74079
75576
|
const emailAccountRemovalActive = () => Boolean(tui.store.ui.emailAccountRemoval);
|
|
75577
|
+
const laneWizardActive = () => Boolean(tui.store.ui.laneWizard);
|
|
75578
|
+
const laneRemovalActive = () => Boolean(tui.store.ui.laneRemoval);
|
|
74080
75579
|
const inputRequestActive = () => Boolean(tui.store.snapshot.pendingUserInput && !tui.store.ui.requestUserInput?.dismissed);
|
|
74081
75580
|
const inputRequestPending = () => Boolean(tui.store.snapshot.pendingUserInput);
|
|
74082
75581
|
const composerSurfaceVisible = () => surface() === "composer";
|
|
@@ -74241,6 +75740,20 @@ function BottomPane() {
|
|
|
74241
75740
|
get children() {
|
|
74242
75741
|
return createComponent2(EmailAccountWizard, {});
|
|
74243
75742
|
}
|
|
75743
|
+
}), createComponent2(Match, {
|
|
75744
|
+
get when() {
|
|
75745
|
+
return surface() === "lane_removal";
|
|
75746
|
+
},
|
|
75747
|
+
get children() {
|
|
75748
|
+
return createComponent2(LaneRemoval, {});
|
|
75749
|
+
}
|
|
75750
|
+
}), createComponent2(Match, {
|
|
75751
|
+
get when() {
|
|
75752
|
+
return surface() === "lane_wizard";
|
|
75753
|
+
},
|
|
75754
|
+
get children() {
|
|
75755
|
+
return createComponent2(LaneWizard, {});
|
|
75756
|
+
}
|
|
74244
75757
|
}), createComponent2(Match, {
|
|
74245
75758
|
get when() {
|
|
74246
75759
|
return surface() === "user_input";
|
|
@@ -74488,6 +76001,8 @@ var init_bottom_pane = __esm(() => {
|
|
|
74488
76001
|
init_mcp_server_wizard();
|
|
74489
76002
|
init_mcp_server_removal();
|
|
74490
76003
|
init_email_account_wizard();
|
|
76004
|
+
init_lane_wizard();
|
|
76005
|
+
init_lane_removal();
|
|
74491
76006
|
init_email_account_removal();
|
|
74492
76007
|
init_slash_autocomplete();
|
|
74493
76008
|
init_renderers2();
|
|
@@ -74598,6 +76113,9 @@ ${note.text}`).join(`
|
|
|
74598
76113
|
},
|
|
74599
76114
|
email: () => {
|
|
74600
76115
|
tui.openEmailOverlay();
|
|
76116
|
+
},
|
|
76117
|
+
subagents: () => {
|
|
76118
|
+
tui.openSubagentsOverlay();
|
|
74601
76119
|
}
|
|
74602
76120
|
}));
|
|
74603
76121
|
onCleanup(disposeCommands);
|
|
@@ -79941,5 +81459,5 @@ Examples:
|
|
|
79941
81459
|
`);
|
|
79942
81460
|
}
|
|
79943
81461
|
|
|
79944
|
-
//# debugId=
|
|
81462
|
+
//# debugId=96D533A4297076F264756E2164756E21
|
|
79945
81463
|
//# sourceMappingURL=index.js.map
|