@a-t-h-i/bot-lobby 0.6.56 → 0.6.57

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-t-h-i/bot-lobby",
3
- "version": "0.6.56",
3
+ "version": "0.6.57",
4
4
  "description": "Structured multi-agent software engineering orchestrator for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -49,6 +49,8 @@ export interface AgentRequest {
49
49
  mcpTools?: string[];
50
50
  /** False when the agent's settings turn its auto-compaction off. */
51
51
  autoCompact?: boolean;
52
+ /** Tokens at which this agent compacts, when its settings set it. */
53
+ compactAt?: number;
52
54
  delegationQuota?: { used: number; consults?: number };
53
55
  /** See PiRunOptions.expert. */
54
56
  expert?: { model?: string; thinking: string };
@@ -186,6 +188,7 @@ async function runAgentOnce(request: AgentRequest, run: ProcessRunner, attempt:
186
188
  mcpTools: request.mcpTools,
187
189
  ...(request.skills ? { skills: request.skills } : {}),
188
190
  ...(request.autoCompact === false ? { autoCompact: false } : {}),
191
+ ...(request.compactAt ? { compactAt: request.compactAt } : {}),
189
192
  task: request.instruction,
190
193
  systemPrompt,
191
194
  tools: toolsFor(request),
@@ -16,6 +16,7 @@ import { runPiAgent, type PiRunOptions, type ProcessRunner } from "./pi-runner.t
16
16
  import { startDeskServer } from "../desk/ipc.ts";
17
17
  import { DESK_ENV, DeskSession, deskSessionAt, PEER_TOOLS } from "../desk/session.ts";
18
18
  import { BOARD_ENV } from "../desk/board.ts";
19
+ import { mcpGrant } from "../pi/grants.ts";
19
20
 
20
21
  export const MAX_CHILDREN = 5;
21
22
  export const DELEGATE_TOOL = "delegate_subtasks";
@@ -95,7 +96,8 @@ export async function delegationHost(options: PiRunOptions, run: ProcessRunner)
95
96
  const quota = options.delegationQuota ?? { used: 0 };
96
97
  const consults = canConsult(agent, config.workflow.consultExpert);
97
98
  const tools = [...new Set([...baseTools, "codemode", "tool_search", ...(canDelegate(agent, quota.used) ? [DELEGATE_TOOL] : []), ...(consults ? [EXPERT_TOOL] : [])])];
98
- const mcpTools = options.mcpTools ?? agentProfile(config, agent.domain, agent.role).mcpTools ?? [];
99
+ // A caller that passes its profile's grant (even an absent one, meaning every connected tool) wins over the role's.
100
+ const mcpTools = mcpGrant("mcpTools" in options ? options.mcpTools : agentProfile(config, agent.domain, agent.role).mcpTools, !editable);
99
101
  const policy: AgentPolicy = { tools, mcpTools, readOnly: !editable, depth };
100
102
  if (depth > 1) return { tools, mcpTools, env: { ...options.env, [AGENT_ENV]: JSON.stringify(policy), [DELEGATION_ENV]: "" }, note: options.env?.[EXPERT_ENV] ? "You are advising a worker: read what you need, answer its question, and change nothing." : "You are a child agent. Finish only your assigned brief and report evidence to your parent; you cannot delegate further.", close: async () => {}, onStart: options.onStart, children: [] as AgentRun[] };
101
103
 
@@ -1,7 +1,7 @@
1
1
  import type { AgentRun } from "../schemas/findings.ts";
2
2
  import type { Domain, Role } from "../schemas/agent.ts";
3
3
  import { delegationHost } from "./delegation.ts";
4
- import { AUTO_COMPACT_ENV } from "../pi/quiet.ts";
4
+ import { AUTO_COMPACT_ENV, COMPACT_AT_ENV } from "../pi/quiet.ts";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { spawn, type ChildProcess } from "node:child_process";
7
7
  import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
@@ -53,6 +53,8 @@ export interface PiRunOptions {
53
53
  env?: Record<string, string>;
54
54
  /** False when the agent's settings turn its auto-compaction off. */
55
55
  autoCompact?: boolean;
56
+ /** Tokens at which the agent compacts its context; absent uses the built-in threshold. */
57
+ compactAt?: number;
56
58
  /** Kill the agent after this long without any output; 0 disables. */
57
59
  stallTimeoutMs?: number;
58
60
  /** Silence allowed while one tool call is in flight (tests, builds); 0 disables. */
@@ -656,7 +658,8 @@ function writePromptFile(prompt: string): { file: string; cleanup: () => void }
656
658
  /** Run one isolated subagent and normalise its outcome. */
657
659
  export async function runPiAgent(given: PiRunOptions, run: ProcessRunner = spawnPiProcess): Promise<PiRunResult> {
658
660
  if (given.harness) return runHarnessAgent({ ...given, harness: given.harness });
659
- const options = given.autoCompact === false ? { ...given, env: { ...given.env, [AUTO_COMPACT_ENV]: "0" } } : given;
661
+ const compactEnv = { ...(given.autoCompact === false ? { [AUTO_COMPACT_ENV]: "0" } : {}), ...(given.compactAt ? { [COMPACT_AT_ENV]: String(given.compactAt) } : {}) };
662
+ const options = Object.keys(compactEnv).length ? { ...given, env: { ...given.env, ...compactEnv } } : given;
660
663
  const host = await delegationHost(options, run);
661
664
  let prompt: ReturnType<typeof writePromptFile> | undefined;
662
665
  try {
@@ -1008,7 +1008,7 @@ export class PlanningSession {
1008
1008
  model,
1009
1009
  thinking,
1010
1010
  mcpTools: profile.mcpTools,
1011
- ...(profile.autoCompact === false ? { autoCompact: false } : {}),
1011
+ ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}),
1012
1012
  // Seats may run on a harness; the planner itself stays on pi (its settings cannot name one).
1013
1013
  ...(profile.harness ? { harness: profile.harness } : {}),
1014
1014
  onChildRun: (child) => {
@@ -279,7 +279,7 @@ export class PullReviews {
279
279
  model,
280
280
  thinking,
281
281
  mcpTools: profile.mcpTools,
282
- ...(profile.autoCompact === false ? { autoCompact: false } : {}),
282
+ ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}),
283
283
  ...(profile.harness ? { harness: profile.harness } : {}),
284
284
  onChildRun: (child) => {
285
285
  this.deps.feed?.step(REVIEW_SOURCE, `child ${child.runId.slice(0, 8)}: ${child.step ?? child.status}`, child.runId);
@@ -98,6 +98,7 @@ export interface QuickFixProfile {
98
98
  autoCompact?: boolean;
99
99
  /** The third-party harness it runs on; absent runs it on pi. */
100
100
  harness?: HarnessRun;
101
+ compactAt?: number;
101
102
  /** Where the job goes when its model runs out of usage or is unavailable. */
102
103
  }
103
104
 
@@ -346,7 +347,7 @@ export class QuickFixQueue {
346
347
  model,
347
348
  thinking,
348
349
  mcpTools: profile.mcpTools,
349
- ...(profile.autoCompact === false ? { autoCompact: false } : {}),
350
+ ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}),
350
351
  ...(profile.harness ? { harness: profile.harness } : {}),
351
352
  delegationQuota: quota,
352
353
  agent: { runId: job.id, taskId: job.id, domain: "backend", role: "worker" },
@@ -101,6 +101,7 @@ export async function runGoalCheck(request: GoalCheckRequest, run: ProcessRunner
101
101
  instruction: goalCheckInstruction(request),
102
102
  context: { task: request.request },
103
103
  systemPrompt: goalCheckPrompt(profile.instructions),
104
+ mcpTools: profile.mcpTools,
104
105
  ...(profile.model ? { model: profile.model } : {}),
105
106
  thinking: profile.thinking,
106
107
  cwd: request.cwd,
@@ -59,7 +59,7 @@ export interface ScoutRequest {
59
59
  /** Model, thinking and grants for one run, from settings. */
60
60
  function profileFields(config: BotLobbyConfig, resolver: ProfileResolver | undefined, domain: Domain, role: AgentRequest["role"]) {
61
61
  const profile = profileFor(config, resolver, domain, role);
62
- return { model: profile.model, mcpTools: profile.mcpTools, ...(profile.skills ? { skills: profile.skills } : {}), ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.harness ? { harness: profile.harness } : {}), thinking: profile.thinking };
62
+ return { model: profile.model, mcpTools: profile.mcpTools, ...(profile.skills ? { skills: profile.skills } : {}), ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}), ...(profile.harness ? { harness: profile.harness } : {}), thinking: profile.thinking };
63
63
  }
64
64
 
65
65
  function scoutInstruction(request: ScoutRequest, domain: Domain): string {
@@ -70,7 +70,7 @@ export async function runResearch(request: ResearchRequest, run: ProcessRunner =
70
70
  model: profile.model,
71
71
  mcpTools: profile.mcpTools,
72
72
  ...(profile.skills ? { skills: profile.skills } : {}),
73
- ...(profile.autoCompact === false ? { autoCompact: false } : {}),
73
+ ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}),
74
74
  ...(profile.harness ? { harness: profile.harness } : {}),
75
75
  thinking: profile.thinking,
76
76
  cwd: request.cwd,
@@ -1,7 +1,8 @@
1
1
  import { compact, CONFIG_DIR_NAME, DEFAULT_COMPACTION_SETTINGS, estimateTokens, findCutPoint, type ExtensionAPI, type ExtensionContext, type TurnEndEvent } from "@earendil-works/pi-coding-agent";
2
2
  import { contextMarks, freshContextOn, staleCompaction } from "./fresh-context.ts";
3
- import { AUTO_COMPACT_ENV, isSubagentProcess } from "./quiet.ts";
3
+ import { AUTO_COMPACT_ENV, COMPACT_AT_ENV, isSubagentProcess } from "./quiet.ts";
4
4
  import { dataRoot, detectProjectRoot, loadConfig } from "../state/project.ts";
5
+ import { normalizeCompactAt } from "../schemas/configuration.ts";
5
6
  import { describeShared, DIGEST_INSTRUCTION, parseDigest, shareDigest, type DigestItem } from "../knowledge/oracle-digest.ts";
6
7
 
7
8
  const CHECKPOINT = "Write a concise checkpoint with: Requirements and constraints; Decisions; Files changed; Verification and evidence; Failed approaches (do not repeat); Unfinished work and next action; Outstanding children and their assignments. Preserve concrete file references and distinguish verified facts from guesses. The parent remains responsible for integration and verification.";
@@ -9,6 +10,8 @@ const CHECKPOINT = "Write a concise checkpoint with: Requirements and constraint
9
10
  export interface AutoCompactionOptions {
10
11
  /** Whether this agent compacts on its own: a subagent by its environment, the oracle by its settings. */
11
12
  enabled?: () => boolean;
13
+ /** The token count set in this agent's settings to compact at; by default its environment, or the oracle's settings. */
14
+ target?: () => number | undefined;
12
15
  /** Where the oracle's shared knowledge goes; by default the project's knowledge files. */
13
16
  share?: (items: DigestItem[], ctx: ExtensionContext) => string;
14
17
  }
@@ -22,6 +25,15 @@ function enabledBySettings(): boolean {
22
25
  }
23
26
  }
24
27
 
28
+ function targetBySettings(): number | undefined {
29
+ if (isSubagentProcess()) return normalizeCompactAt(Number(process.env[COMPACT_AT_ENV]));
30
+ try {
31
+ return loadConfig().master.compactAt;
32
+ } catch {
33
+ return undefined;
34
+ }
35
+ }
36
+
25
37
  function shareWithAgents(items: DigestItem[], ctx: ExtensionContext): string {
26
38
  const root = detectProjectRoot(ctx.cwd, CONFIG_DIR_NAME);
27
39
  return describeShared(shareDigest(dataRoot(root, CONFIG_DIR_NAME), items));
@@ -29,18 +41,24 @@ function shareWithAgents(items: DigestItem[], ctx: ExtensionContext): string {
29
41
 
30
42
  export const CONTEXT_TARGET = 64_000;
31
43
 
32
- export function compactionThreshold(window: number, reserve = DEFAULT_COMPACTION_SETTINGS.reserveTokens): number {
33
- return Math.max(1, Math.min(CONTEXT_TARGET, Math.floor(window * 0.6), window - Math.min(reserve, Math.floor(window / 2))));
44
+ /**
45
+ * When to compact: a threshold set in Settings, else 64K or 60% of the window, whichever is smaller. Either way it
46
+ * stays below the window less pi's reserve, so the checkpoint still has room to be written.
47
+ */
48
+ export function compactionThreshold(window: number, reserve = DEFAULT_COMPACTION_SETTINGS.reserveTokens, target?: number): number {
49
+ const room = window - Math.min(reserve, Math.floor(window / 2));
50
+ return Math.max(1, Math.min(target ?? Math.min(CONTEXT_TARGET, Math.floor(window * 0.6)), room));
34
51
  }
35
52
 
36
53
  /**
37
54
  * Compact at a settled tool boundary, below pi's own threshold (pi 1.3 still sets that only per model in settings, and
38
- * ctx.compact() would abort the turn we need to continue). Each agent's settings can turn it off. Compactions pi
55
+ * ctx.compact() would abort the turn we need to continue). Each agent's settings can turn it off or set the token count it starts at. Compactions pi
39
56
  * starts itself get the same checkpoint through `session_before_compact`. The oracle's checkpoint also lists what it learned that is worth keeping, tagged by agent, and
40
57
  * that goes into the knowledge base: its own, and the designer's, backend's and QA's where it concerns them.
41
58
  */
42
59
  export function registerAutoCompaction(pi: ExtensionAPI, summarize: typeof compact = compact, options: AutoCompactionOptions = {}): void {
43
60
  const enabled = options.enabled ?? enabledBySettings;
61
+ const target = options.target ?? targetBySettings;
44
62
  const share = options.share ?? shareWithAgents;
45
63
  const oracle = !isSubagentProcess();
46
64
  let busy = false;
@@ -53,7 +71,7 @@ export function registerAutoCompaction(pi: ExtensionAPI, summarize: typeof compa
53
71
  const configured = pi.getSettings().compaction;
54
72
  const override = configured?.modelOverrides?.[`${ctx.model.provider}/${ctx.model.id}`];
55
73
  const reserve = Math.min(override?.reserveTokens ?? configured?.reserveTokens ?? DEFAULT_COMPACTION_SETTINGS.reserveTokens, Math.floor(ctx.model.contextWindow / 2));
56
- const threshold = compactionThreshold(ctx.model.contextWindow, reserve);
74
+ const threshold = compactionThreshold(ctx.model.contextWindow, reserve, target());
57
75
  const estimate = event.context.contextMessages.reduce((total, message) => total + estimateTokens(message), 0) + Math.ceil(ctx.getSystemPrompt().length / 4);
58
76
  const usage = ctx.getContextUsage();
59
77
  if (Math.max(estimate, usage?.tokens ?? 0) < threshold) return;
@@ -27,8 +27,9 @@ export function registerAgentPermissions(pi: ExtensionAPI): void {
27
27
  if (!info) return { block: true, reason: `Unknown tool ${event.toolName}.` };
28
28
  if (["list_mcp_resources", "list_mcp_resource_templates", "read_mcp_resource"].includes(event.toolName)) {
29
29
  const server = (event.input as { server?: unknown }).server;
30
- const grants = policy?.mcpTools ?? loadConfig().master.mcpTools ?? [];
31
- if (typeof server === "string" && grants.some((tool) => tool.startsWith(`mcp__${server.replace(/[^A-Za-z0-9_]/g, "_")}__`)) && info?.exposure !== "hidden") return;
30
+ // The oracle with no list in its settings may use every connected server.
31
+ const grants = policy?.mcpTools ?? loadConfig().master.mcpTools;
32
+ if (typeof server === "string" && (!grants || grants.some((tool) => tool.startsWith(`mcp__${server.replace(/[^A-Za-z0-9_]/g, "_")}__`))) && info?.exposure !== "hidden") return;
32
33
  return { block: true, reason: "Specify an MCP server with an explicit tool grant to read its resources." };
33
34
  }
34
35
  if (policy) {
@@ -36,7 +37,8 @@ export function registerAgentPermissions(pi: ExtensionAPI): void {
36
37
  return { block: true, reason: `This agent is not granted ${event.toolName}.` };
37
38
  }
38
39
  if (event.toolName.startsWith("mcp__")) {
39
- if ((loadConfig().master.mcpTools ?? []).includes(event.toolName) && info?.exposure !== "hidden") return;
40
+ const granted = loadConfig().master.mcpTools;
41
+ if ((!granted || granted.includes(event.toolName)) && info?.exposure !== "hidden") return;
40
42
  return { block: true, reason: `Grant ${event.toolName} to the master in bot-lobby settings first.` };
41
43
  }
42
44
  if (event.parentToolCallId && !pi.getActiveTools().includes(event.toolName)) return { block: true, reason: `${event.toolName} is not active for this agent.` };
package/src/pi/grants.ts CHANGED
@@ -55,6 +55,16 @@ export function grantableTools(pi: ExtensionAPI | undefined = source): Grantable
55
55
  .sort((a, b) => a.server.localeCompare(b.server) || a.name.localeCompare(b.name));
56
56
  }
57
57
 
58
+ /**
59
+ * The MCP tools a run may call: its settings' list as given, or, when the
60
+ * settings name none, every tool pi has connected now (only the read-only ones
61
+ * for an agent that must not change anything).
62
+ */
63
+ export function mcpGrant(granted: readonly string[] | undefined, readOnly: boolean, pi: ExtensionAPI | undefined = source): string[] {
64
+ if (granted) return [...granted];
65
+ return grantableTools(pi).filter((tool) => !readOnly || tool.readOnly).map((tool) => tool.name);
66
+ }
67
+
58
68
  /**
59
69
  * The skills an agent working in `cwd` would find: the session's own (its
60
70
  * skill commands, which include packages and settings paths) and pi's default
@@ -94,7 +94,7 @@ export function createProfileResolver(config: BotLobbyConfig, options: ResolverO
94
94
  };
95
95
  }
96
96
 
97
- type RunProfile = { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; harness?: HarnessRun };
97
+ type RunProfile = { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; compactAt?: number; harness?: HarnessRun };
98
98
 
99
99
  /** Unset models run on the session's; thinking is clamped to the model, with a one-time warning. */
100
100
  function resolveRunProfile(profile: RunProfile, label: string, options: ResolverOptions): RunProfile {
@@ -133,7 +133,7 @@ export function resolvePanelProfile(config: BotLobbyConfig, member: PanelMember,
133
133
  */
134
134
  export function resolveReviewProfile(config: BotLobbyConfig, options: ResolverOptions): RunProfile {
135
135
  const profile = agentProfile(config, "qa", "reviewer");
136
- return resolveRunProfile({ model: profile.model, thinking: profile.thinking, ...(profile.instructions ? { instructions: profile.instructions } : {}), ...(profile.mcpTools ? { mcpTools: profile.mcpTools } : {}), ...(profile.skills ? { skills: profile.skills } : {}), ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.harness ? { harness: profile.harness } : {}) }, kindLabel("qa"), options);
136
+ return resolveRunProfile({ model: profile.model, thinking: profile.thinking, ...(profile.instructions ? { instructions: profile.instructions } : {}), ...(profile.mcpTools ? { mcpTools: profile.mcpTools } : {}), ...(profile.skills ? { skills: profile.skills } : {}), ...(profile.autoCompact === false ? { autoCompact: false } : {}), ...(profile.compactAt ? { compactAt: profile.compactAt } : {}), ...(profile.harness ? { harness: profile.harness } : {}) }, kindLabel("qa"), options);
137
137
  }
138
138
 
139
139
  /** Every configured subagent whose thinking level its model does not support, for `/bot-lobby config`. */
package/src/pi/quiet.ts CHANGED
@@ -60,6 +60,8 @@ export function webToolsFor(active: string[], taskActive: boolean, hidden: reado
60
60
 
61
61
  /** Set to "0" in a subagent's environment when its settings turn auto-compaction off. */
62
62
  export const AUTO_COMPACT_ENV = "BOT_LOBBY_AUTO_COMPACT";
63
+ /** The token count at which a subagent compacts, from its settings. */
64
+ export const COMPACT_AT_ENV = "BOT_LOBBY_COMPACT_AT";
63
65
 
64
66
  /** True inside a bot-lobby subagent process (marked in `spawnPiProcess`). */
65
67
  export function isSubagentProcess(): boolean {
@@ -28,12 +28,14 @@ export interface AgentModelConfig extends HarnessChoice {
28
28
  thinking: string;
29
29
  /** Free-form instructions layered on top of this agent's built-in prompt. */
30
30
  instructions?: string;
31
- /** Exact native MCP tool names this profile may call; empty grants none. */
31
+ /** Exact native MCP tool names this profile may call; absent gives it every tool pi has connected (read-only ones for read-only agents), empty gives it none. */
32
32
  mcpTools?: string[];
33
33
  /** Names of the skills this agent may load; absent gives it every skill pi finds, empty gives it none. */
34
34
  skills?: string[];
35
35
  /** Compact this agent's context on its own as it fills (on unless false); the oracle's also updates the knowledge base. */
36
36
  autoCompact?: boolean;
37
+ /** Context size, in tokens, at which auto-compaction starts; absent uses the built-in threshold. */
38
+ compactAt?: number;
37
39
  }
38
40
 
39
41
  /** Scouts pick a model only; their thinking is fixed at `SCOUT_THINKING`. */
@@ -46,6 +48,8 @@ export interface ScoutConfig extends HarnessChoice {
46
48
  maxToolCalls: number;
47
49
  /** Compact a scout's context on its own as it fills (on unless false). */
48
50
  autoCompact?: boolean;
51
+ /** See AgentModelConfig.compactAt. */
52
+ compactAt?: number;
49
53
  }
50
54
 
51
55
  /** Subagent kinds with their own settings entry. */
@@ -380,6 +384,26 @@ export function normalizeMcpTools(value: unknown): string[] {
380
384
  return Array.isArray(value) ? [...new Set(value.filter((tool): tool is string => typeof tool === "string" && /^mcp__[A-Za-z0-9_]+__[A-Za-z0-9_]+$/.test(tool)))] : [];
381
385
  }
382
386
 
387
+ /** `{ mcpTools }` when an entry lists its tools (even none), else nothing, so the agent keeps every connected tool. */
388
+ function mcpToolsField(value: unknown): { mcpTools?: string[] } {
389
+ return Array.isArray(value) ? { mcpTools: normalizeMcpTools(value) } : {};
390
+ }
391
+
392
+ /** The smallest and largest auto-compaction thresholds Settings accepts, in tokens. */
393
+ export const COMPACT_AT_MIN = 4_000;
394
+ export const COMPACT_AT_MAX = 2_000_000;
395
+
396
+ /** A whole number of tokens within the accepted range, or absent for the built-in threshold. */
397
+ export function normalizeCompactAt(value: unknown): number | undefined {
398
+ return typeof value === "number" && Number.isFinite(value) && value >= COMPACT_AT_MIN && value <= COMPACT_AT_MAX ? Math.round(value) : undefined;
399
+ }
400
+
401
+ /** Auto-compaction off and its threshold, when an entry sets them. */
402
+ function compactFields(entry: { autoCompact?: unknown; compactAt?: unknown } | undefined): { autoCompact?: false; compactAt?: number } {
403
+ const compactAt = normalizeCompactAt(entry?.compactAt);
404
+ return { ...(entry?.autoCompact === false ? { autoCompact: false } : {}), ...(compactAt ? { compactAt } : {}) };
405
+ }
406
+
383
407
  /**
384
408
  * Merge one agent's override over its default; legacy `inherit` or unknown
385
409
  * thinking falls back to the default level. Only subagents may name a
@@ -389,21 +413,19 @@ export function normalizeMcpTools(value: unknown): string[] {
389
413
  function normalizeAgent(base: AgentModelConfig, override: Partial<AgentModelConfig> | undefined, harness = true): AgentModelConfig {
390
414
  const merged = { ...base, ...(override ?? {}) };
391
415
  const thinking = isThinkingLevel(merged.thinking) ? merged.thinking : base.thinking;
392
- const mcpTools = normalizeMcpTools(merged.mcpTools);
393
416
  const choice = harness ? harnessChoiceFields(merged) : {};
394
- return { model: merged.model, thinking, ...(mcpTools.length ? { mcpTools } : {}), ...skillsField(merged.skills), ...(typeof merged.instructions === "string" ? { instructions: merged.instructions } : {}), ...(merged.autoCompact === false ? { autoCompact: false } : {}), ...choice };
417
+ return { model: merged.model, thinking, ...mcpToolsField(merged.mcpTools), ...skillsField(merged.skills), ...(typeof merged.instructions === "string" ? { instructions: merged.instructions } : {}), ...compactFields(merged), ...choice };
395
418
  }
396
419
 
397
420
  /** Scouts keep a model and a tool-call cap; any thinking value in the file is dropped. */
398
421
  function normalizeScout(override: Partial<ScoutConfig> | undefined): ScoutConfig {
399
422
  const base = DEFAULT_CONFIG.scout;
400
- const mcpTools = normalizeMcpTools(override?.mcpTools);
401
423
  return {
402
424
  model: typeof override?.model === "string" && override.model.trim() ? override.model : base.model,
403
425
  maxToolCalls: typeof override?.maxToolCalls === "number" && Number.isFinite(override.maxToolCalls) && override.maxToolCalls >= 0 ? Math.round(override.maxToolCalls) : base.maxToolCalls,
404
- ...(mcpTools.length ? { mcpTools } : {}),
426
+ ...mcpToolsField(override?.mcpTools),
405
427
  ...skillsField(override?.skills),
406
- ...(override?.autoCompact === false ? { autoCompact: false } : {}),
428
+ ...compactFields(override),
407
429
  ...harnessChoiceFields(override ?? {}),
408
430
  };
409
431
  }
@@ -559,12 +581,14 @@ export interface AgentProfile {
559
581
  model?: string;
560
582
  thinking: string;
561
583
  instructions?: string;
562
- /** Exact native MCP tool names this profile may call; empty grants none. */
584
+ /** Exact native MCP tool names this profile may call; absent keeps every connected tool, empty grants none. */
563
585
  mcpTools?: string[];
564
586
  /** Skill names it may load; absent keeps every skill pi finds. */
565
587
  skills?: string[];
566
588
  /** False when its settings turn auto-compaction off. */
567
589
  autoCompact?: boolean;
590
+ /** Tokens at which auto-compaction starts, when set. */
591
+ compactAt?: number;
568
592
  /** The third-party harness it runs on; absent runs it on pi. */
569
593
  harness?: HarnessRun;
570
594
  }
@@ -575,14 +599,14 @@ function harnessField(config: BotLobbyConfig, entry: HarnessChoice): { harness?:
575
599
  return harness ? { harness } : {};
576
600
  }
577
601
 
578
- /** `{ autoCompact: false }` when an entry turns auto-compaction off, else nothing. */
579
- function compactField(entry: { autoCompact?: boolean }): { autoCompact?: false } {
580
- return entry.autoCompact === false ? { autoCompact: false } : {};
602
+ /** Auto-compaction off and its threshold, as an entry sets them. */
603
+ function compactField(entry: { autoCompact?: boolean; compactAt?: number }): { autoCompact?: false; compactAt?: number } {
604
+ return { ...(entry.autoCompact === false ? { autoCompact: false } : {}), ...(entry.compactAt ? { compactAt: entry.compactAt } : {}) };
581
605
  }
582
606
 
583
607
  /** The MCP tools and skills an entry grants, leaving out what it does not name. */
584
608
  function grantFields(entry: { mcpTools?: string[]; skills?: string[] }): { mcpTools?: string[]; skills?: string[] } {
585
- return { ...(entry.mcpTools?.length ? { mcpTools: entry.mcpTools } : {}), ...(entry.skills ? { skills: entry.skills } : {}) };
609
+ return { ...(entry.mcpTools ? { mcpTools: entry.mcpTools } : {}), ...(entry.skills ? { skills: entry.skills } : {}) };
586
610
  }
587
611
 
588
612
  /** The settings entry a domain/role run draws from. */
@@ -618,7 +642,7 @@ export function lobbyAgentConfig(config: BotLobbyConfig, kind: LobbyAgentKind):
618
642
  }
619
643
 
620
644
  /** Profile for a lobby agent run, from settings alone; `model` is undefined while unset. */
621
- export function lobbyAgentProfile(config: BotLobbyConfig, kind: LobbyAgentKind): { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; harness?: HarnessRun } {
645
+ export function lobbyAgentProfile(config: BotLobbyConfig, kind: LobbyAgentKind): { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; compactAt?: number; harness?: HarnessRun } {
622
646
  const entry = lobbyAgentConfig(config, kind);
623
647
  return { model: modelOf(entry.model), thinking: entry.thinking, instructions: entry.instructions, ...grantFields(entry), ...compactField(entry), ...harnessField(config, entry) };
624
648
  }
@@ -627,7 +651,7 @@ export function lobbyAgentProfile(config: BotLobbyConfig, kind: LobbyAgentKind):
627
651
  * A planning panel seat's profile: the domain's (or the researcher's) model,
628
652
  * thinking, custom instructions and grants.
629
653
  */
630
- export function panelMemberProfile(config: BotLobbyConfig, member: PanelMember): { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; harness?: HarnessRun } {
654
+ export function panelMemberProfile(config: BotLobbyConfig, member: PanelMember): { model?: string; thinking: string; instructions?: string; mcpTools?: string[]; skills?: string[]; autoCompact?: boolean; compactAt?: number; harness?: HarnessRun } {
631
655
  const entry = member === "researcher" ? config.researcher : config.agents[member];
632
656
  return { model: modelOf(entry.model), thinking: entry.thinking, instructions: entry.instructions, ...grantFields(entry), ...compactField(entry), ...harnessField(config, entry) };
633
657
  }
@@ -1,4 +1,4 @@
1
- import{a as e,i as t,n,o as r,r as i,t as a}from"./index-BKiKxUUG.js";var o=r(e(),1),s=Object.defineProperty,c=Object.getOwnPropertyDescriptor,l=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{for(var i=r>1?void 0:r?c(t,n):t,a=e.length-1,o;a>=0;a--)(o=e[a])&&(i=(r?o(t,n,i):o(i))||i);return r&&i&&s(t,n,i),i},d=(e,t)=>(n,r)=>t(n,r,e),f=`Terminal input`,p={get:()=>f,set:e=>f=e},m=`Too much output to announce, navigate to rows manually to read`,h={get:()=>m,set:e=>m=e};function g(e){return e.replace(/\r?\n/g,`\r`)}function _(e,t){return t?`\x1B[200~`+e+`\x1B[201~`:e}function ee(e,t){e.clipboardData&&e.clipboardData.setData(`text/plain`,t.selectionText),e.preventDefault()}function te(e,t,n,r){e.stopPropagation(),e.clipboardData&&ne(e.clipboardData.getData(`text/plain`),t,n,r)}function ne(e,t,n,r){e=g(e),e=_(e,n.decPrivateModes.bracketedPasteMode&&r.rawOptions.ignoreBracketedPasteMode!==!0),n.triggerDataEvent(e,!0),t.value=``}function re(e,t,n){let r=n.getBoundingClientRect(),i=e.clientX-r.left-10,a=e.clientY-r.top-10;t.style.width=`20px`,t.style.height=`20px`,t.style.left=`${i}px`,t.style.top=`${a}px`,t.style.zIndex=`1000`,t.focus()}function ie(e,t,n,r,i){re(e,t,n),i&&r.rightClickSelect(e),t.value=r.selectionText,t.select()}function ae(e){return e>65535?(e-=65536,String.fromCharCode((e>>10)+55296)+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)}function oe(e,t=0,n=e.length){let r=``;for(let i=t;i<n;++i){let t=e[i];t>65535?(t-=65536,r+=String.fromCharCode((t>>10)+55296)+String.fromCharCode(t%1024+56320)):r+=String.fromCharCode(t)}return r}var se=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i=0;if(this._interim){let n=e.charCodeAt(i++);56320<=n&&n<=57343?t[r++]=(this._interim-55296)*1024+n-56320+65536:(t[r++]=this._interim,t[r++]=n),this._interim=0}for(let a=i;a<n;++a){let i=e.charCodeAt(a);if(55296<=i&&i<=56319){if(++a>=n)return this._interim=i,r;let o=e.charCodeAt(a);56320<=o&&o<=57343?t[r++]=(i-55296)*1024+o-56320+65536:(t[r++]=i,t[r++]=o);continue}i!==65279&&(t[r++]=i)}return r}},ce=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i,a,o,s,c=0,l=0;if(this.interim[0]){let i=!1,a=this.interim[0];a&=(a&224)==192?31:(a&240)==224?15:7;let o=0,s;for(;(s=this.interim[++o]&63)&&o<4;)a<<=6,a|=s;let c=(this.interim[0]&224)==192?2:(this.interim[0]&240)==224?3:4,u=c-o;for(;l<u;){if(l>=n)return 0;if(s=e[l++],(s&192)!=128){l--,i=!0;break}this.interim[o++]=s,a<<=6,a|=s&63}i||(c===2?a<128?l--:t[r++]=a:c===3?a<2048||a>=55296&&a<=57343||a===65279||(t[r++]=a):a<65536||a>1114111||(t[r++]=a)),this.interim.fill(0)}let u=n-4,d=l;for(;d<n;){for(;d<u&&!((i=e[d])&128)&&!((a=e[d+1])&128)&&!((o=e[d+2])&128)&&!((s=e[d+3])&128);)t[r++]=i,t[r++]=a,t[r++]=o,t[r++]=s,d+=4;if(i=e[d++],i<128)t[r++]=i;else if((i&224)==192){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(c=(i&31)<<6|a&63,c<128){d--;continue}t[r++]=c}else if((i&240)==224){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(c=(i&15)<<12|(a&63)<<6|o&63,c<2048||c>=55296&&c<=57343||c===65279)continue;t[r++]=c}else if((i&248)==240){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,this.interim[2]=o,r;if(s=e[d++],(s&192)!=128){d--;continue}if(c=(i&7)<<18|(a&63)<<12|(o&63)<<6|s&63,c<65536||c>1114111)continue;t[r++]=c}}return r}},v=``,le=` `,ue=class e{constructor(){this.fg=0,this.bg=0,this.extended=new de}static toColorRGB(e){return[e>>>16&255,e>>>8&255,e&255]}static fromColorRGB(e){return(e[0]&255)<<16|(e[1]&255)<<8|e[2]&255}clone(){let t=new e;return t.fg=this.fg,t.bg=this.bg,t.extended=this.extended.clone(),t}isInverse(){return this.fg&67108864}isBold(){return this.fg&134217728}isUnderline(){return this.hasExtendedAttrs()&&this.extended.underlineStyle!==0?1:this.fg&268435456}isBlink(){return this.fg&536870912}isInvisible(){return this.fg&1073741824}isItalic(){return this.bg&67108864}isDim(){return this.bg&134217728}isStrikethrough(){return this.fg&2147483648}isProtected(){return this.bg&536870912}isOverline(){return this.bg&1073741824}getFgColorMode(){return this.fg&50331648}getBgColorMode(){return this.bg&50331648}isFgRGB(){return(this.fg&50331648)==50331648}isBgRGB(){return(this.bg&50331648)==50331648}isFgPalette(){return(this.fg&50331648)==16777216||(this.fg&50331648)==33554432}isBgPalette(){return(this.bg&50331648)==16777216||(this.bg&50331648)==33554432}isFgDefault(){return!(this.fg&50331648)}isBgDefault(){return!(this.bg&50331648)}isAttributeDefault(){return this.fg===0&&this.bg===0}getFgColor(){switch(this.fg&50331648){case 16777216:case 33554432:return this.fg&255;case 50331648:return this.fg&16777215;default:return-1}}getBgColor(){switch(this.bg&50331648){case 16777216:case 33554432:return this.bg&255;case 50331648:return this.bg&16777215;default:return-1}}hasExtendedAttrs(){return this.bg&268435456}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(this.bg&268435456&&~this.extended.underlineColor)switch(this.extended.underlineColor&50331648){case 16777216:case 33554432:return this.extended.underlineColor&255;case 50331648:return this.extended.underlineColor&16777215;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return this.bg&268435456&&~this.extended.underlineColor?this.extended.underlineColor&50331648:this.getFgColorMode()}isUnderlineColorRGB(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==50331648:this.isFgRGB()}isUnderlineColorPalette(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==16777216||(this.extended.underlineColor&50331648)==33554432:this.isFgPalette()}isUnderlineColorDefault(){return this.bg&268435456&&~this.extended.underlineColor?!(this.extended.underlineColor&50331648):this.isFgDefault()}getUnderlineStyle(){return this.fg&268435456?this.bg&268435456?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}},de=class e{constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}get ext(){return this._urlId?this._ext&-469762049|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(this._ext&469762048)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return this._ext&67108863}set underlineColor(e){this._ext&=-67108864,this._ext|=e&67108863}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){let e=(this._ext&3758096384)>>29;return e<0?e^4294967288:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}clone(){return new e(this._ext,this._urlId)}isEmpty(){return this.underlineStyle===0&&this._urlId===0}},y=class e extends ue{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new de,this.combinedData=``}static fromCharData(t){let n=new e;return n.setFromCharData(t),n}isCombined(){return this.content&2097152}getWidth(){return this.content>>22}getChars(){return this.content&2097152?this.combinedData:this.content&2097151?ae(this.content&2097151):``}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):this.content&2097151}setFromCharData(e){this.fg=e[0],this.bg=0;let t=!1;if(e[1].length>2)t=!0;else if(e[1].length===2){let n=e[1].charCodeAt(0);if(55296<=n&&n<=56319){let r=e[1].charCodeAt(1);56320<=r&&r<=57343?this.content=(n-55296)*1024+r-56320+65536|e[2]<<22:t=!0}else t=!0}else this.content=e[1].charCodeAt(0)|e[2]<<22;t&&(this.combinedData=e[1],this.content=2097152|e[2]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}},fe=`di$target`,pe=`di$dependencies`,me=new Map;function b(e){return e[pe]||[]}function x(e){if(me.has(e))return me.get(e);let t=function(e,n,r){if(arguments.length!==3)throw Error(`@IServiceName-decorator can only be used to decorate a parameter`);he(t,e,r)};return t._id=e,me.set(e,t),t}function he(e,t,n){t[fe]===t?t[pe].push({id:e,index:n}):(t[pe]=[{id:e,index:n}],t[fe]=t)}var S=x(`BufferService`),ge=x(`CoreMouseService`),_e=x(`CoreService`),C=x(`CharsetService`),ve=x(`InstantiationService`),w=x(`LogService`),T=x(`OptionsService`),ye=x(`OscLinkService`),be=x(`UnicodeService`),xe=x(`DecorationService`),Se=class{constructor(e,t,n){this._bufferService=e,this._optionsService=t,this._oscLinkService=n}provideLinks(e,t){let n=this._bufferService.buffer.lines.get(e-1);if(!n){t(void 0);return}let r=[],i=this._optionsService.rawOptions.linkHandler,a=new y,o=n.getTrimmedLength(),s=-1,c=-1,l=!1;for(let t=0;t<o;t++)if(c!==-1||n.hasContent(t)){if(n.loadCell(t,a),a.hasExtendedAttrs()&&a.extended.urlId){if(c===-1){c=t,s=a.extended.urlId;continue}l=a.extended.urlId!==s}else c!==-1&&(l=!0);if(l||c!==-1&&t===o-1){let n=this._oscLinkService.getLinkData(s)?.uri;if(n){let a={start:{x:c+1,y:e},end:{x:t+ +(!l&&t===o-1),y:e}},s=!1;if(!i?.allowNonHttpProtocols)try{let e=new URL(n);[`http:`,`https:`].includes(e.protocol)||(s=!0)}catch{s=!0}s||r.push({text:n,range:a,activate:(e,t)=>i?i.activate(e,t,a):Ce(e,t),hover:(e,t)=>i?.hover?.(e,t,a),leave:(e,t)=>i?.leave?.(e,t,a)})}l=!1,a.hasExtendedAttrs()&&a.extended.urlId?(c=t,s=a.extended.urlId):(c=-1,s=-1)}}t(r)}};Se=u([d(0,S),d(1,T),d(2,ye)],Se);function Ce(e,t){if(confirm(`Do you want to navigate to ${t}?
1
+ import{a as e,i as t,n,o as r,r as i,t as a}from"./index-Bs1_77_1.js";var o=r(e(),1),s=Object.defineProperty,c=Object.getOwnPropertyDescriptor,l=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},u=(e,t,n,r)=>{for(var i=r>1?void 0:r?c(t,n):t,a=e.length-1,o;a>=0;a--)(o=e[a])&&(i=(r?o(t,n,i):o(i))||i);return r&&i&&s(t,n,i),i},d=(e,t)=>(n,r)=>t(n,r,e),f=`Terminal input`,p={get:()=>f,set:e=>f=e},m=`Too much output to announce, navigate to rows manually to read`,h={get:()=>m,set:e=>m=e};function g(e){return e.replace(/\r?\n/g,`\r`)}function _(e,t){return t?`\x1B[200~`+e+`\x1B[201~`:e}function ee(e,t){e.clipboardData&&e.clipboardData.setData(`text/plain`,t.selectionText),e.preventDefault()}function te(e,t,n,r){e.stopPropagation(),e.clipboardData&&ne(e.clipboardData.getData(`text/plain`),t,n,r)}function ne(e,t,n,r){e=g(e),e=_(e,n.decPrivateModes.bracketedPasteMode&&r.rawOptions.ignoreBracketedPasteMode!==!0),n.triggerDataEvent(e,!0),t.value=``}function re(e,t,n){let r=n.getBoundingClientRect(),i=e.clientX-r.left-10,a=e.clientY-r.top-10;t.style.width=`20px`,t.style.height=`20px`,t.style.left=`${i}px`,t.style.top=`${a}px`,t.style.zIndex=`1000`,t.focus()}function ie(e,t,n,r,i){re(e,t,n),i&&r.rightClickSelect(e),t.value=r.selectionText,t.select()}function ae(e){return e>65535?(e-=65536,String.fromCharCode((e>>10)+55296)+String.fromCharCode(e%1024+56320)):String.fromCharCode(e)}function oe(e,t=0,n=e.length){let r=``;for(let i=t;i<n;++i){let t=e[i];t>65535?(t-=65536,r+=String.fromCharCode((t>>10)+55296)+String.fromCharCode(t%1024+56320)):r+=String.fromCharCode(t)}return r}var se=class{constructor(){this._interim=0}clear(){this._interim=0}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i=0;if(this._interim){let n=e.charCodeAt(i++);56320<=n&&n<=57343?t[r++]=(this._interim-55296)*1024+n-56320+65536:(t[r++]=this._interim,t[r++]=n),this._interim=0}for(let a=i;a<n;++a){let i=e.charCodeAt(a);if(55296<=i&&i<=56319){if(++a>=n)return this._interim=i,r;let o=e.charCodeAt(a);56320<=o&&o<=57343?t[r++]=(i-55296)*1024+o-56320+65536:(t[r++]=i,t[r++]=o);continue}i!==65279&&(t[r++]=i)}return r}},ce=class{constructor(){this.interim=new Uint8Array(3)}clear(){this.interim.fill(0)}decode(e,t){let n=e.length;if(!n)return 0;let r=0,i,a,o,s,c=0,l=0;if(this.interim[0]){let i=!1,a=this.interim[0];a&=(a&224)==192?31:(a&240)==224?15:7;let o=0,s;for(;(s=this.interim[++o]&63)&&o<4;)a<<=6,a|=s;let c=(this.interim[0]&224)==192?2:(this.interim[0]&240)==224?3:4,u=c-o;for(;l<u;){if(l>=n)return 0;if(s=e[l++],(s&192)!=128){l--,i=!0;break}this.interim[o++]=s,a<<=6,a|=s&63}i||(c===2?a<128?l--:t[r++]=a:c===3?a<2048||a>=55296&&a<=57343||a===65279||(t[r++]=a):a<65536||a>1114111||(t[r++]=a)),this.interim.fill(0)}let u=n-4,d=l;for(;d<n;){for(;d<u&&!((i=e[d])&128)&&!((a=e[d+1])&128)&&!((o=e[d+2])&128)&&!((s=e[d+3])&128);)t[r++]=i,t[r++]=a,t[r++]=o,t[r++]=s,d+=4;if(i=e[d++],i<128)t[r++]=i;else if((i&224)==192){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(c=(i&31)<<6|a&63,c<128){d--;continue}t[r++]=c}else if((i&240)==224){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(c=(i&15)<<12|(a&63)<<6|o&63,c<2048||c>=55296&&c<=57343||c===65279)continue;t[r++]=c}else if((i&248)==240){if(d>=n)return this.interim[0]=i,r;if(a=e[d++],(a&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,r;if(o=e[d++],(o&192)!=128){d--;continue}if(d>=n)return this.interim[0]=i,this.interim[1]=a,this.interim[2]=o,r;if(s=e[d++],(s&192)!=128){d--;continue}if(c=(i&7)<<18|(a&63)<<12|(o&63)<<6|s&63,c<65536||c>1114111)continue;t[r++]=c}}return r}},v=``,le=` `,ue=class e{constructor(){this.fg=0,this.bg=0,this.extended=new de}static toColorRGB(e){return[e>>>16&255,e>>>8&255,e&255]}static fromColorRGB(e){return(e[0]&255)<<16|(e[1]&255)<<8|e[2]&255}clone(){let t=new e;return t.fg=this.fg,t.bg=this.bg,t.extended=this.extended.clone(),t}isInverse(){return this.fg&67108864}isBold(){return this.fg&134217728}isUnderline(){return this.hasExtendedAttrs()&&this.extended.underlineStyle!==0?1:this.fg&268435456}isBlink(){return this.fg&536870912}isInvisible(){return this.fg&1073741824}isItalic(){return this.bg&67108864}isDim(){return this.bg&134217728}isStrikethrough(){return this.fg&2147483648}isProtected(){return this.bg&536870912}isOverline(){return this.bg&1073741824}getFgColorMode(){return this.fg&50331648}getBgColorMode(){return this.bg&50331648}isFgRGB(){return(this.fg&50331648)==50331648}isBgRGB(){return(this.bg&50331648)==50331648}isFgPalette(){return(this.fg&50331648)==16777216||(this.fg&50331648)==33554432}isBgPalette(){return(this.bg&50331648)==16777216||(this.bg&50331648)==33554432}isFgDefault(){return!(this.fg&50331648)}isBgDefault(){return!(this.bg&50331648)}isAttributeDefault(){return this.fg===0&&this.bg===0}getFgColor(){switch(this.fg&50331648){case 16777216:case 33554432:return this.fg&255;case 50331648:return this.fg&16777215;default:return-1}}getBgColor(){switch(this.bg&50331648){case 16777216:case 33554432:return this.bg&255;case 50331648:return this.bg&16777215;default:return-1}}hasExtendedAttrs(){return this.bg&268435456}updateExtended(){this.extended.isEmpty()?this.bg&=-268435457:this.bg|=268435456}getUnderlineColor(){if(this.bg&268435456&&~this.extended.underlineColor)switch(this.extended.underlineColor&50331648){case 16777216:case 33554432:return this.extended.underlineColor&255;case 50331648:return this.extended.underlineColor&16777215;default:return this.getFgColor()}return this.getFgColor()}getUnderlineColorMode(){return this.bg&268435456&&~this.extended.underlineColor?this.extended.underlineColor&50331648:this.getFgColorMode()}isUnderlineColorRGB(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==50331648:this.isFgRGB()}isUnderlineColorPalette(){return this.bg&268435456&&~this.extended.underlineColor?(this.extended.underlineColor&50331648)==16777216||(this.extended.underlineColor&50331648)==33554432:this.isFgPalette()}isUnderlineColorDefault(){return this.bg&268435456&&~this.extended.underlineColor?!(this.extended.underlineColor&50331648):this.isFgDefault()}getUnderlineStyle(){return this.fg&268435456?this.bg&268435456?this.extended.underlineStyle:1:0}getUnderlineVariantOffset(){return this.extended.underlineVariantOffset}},de=class e{constructor(e=0,t=0){this._ext=0,this._urlId=0,this._ext=e,this._urlId=t}get ext(){return this._urlId?this._ext&-469762049|this.underlineStyle<<26:this._ext}set ext(e){this._ext=e}get underlineStyle(){return this._urlId?5:(this._ext&469762048)>>26}set underlineStyle(e){this._ext&=-469762049,this._ext|=e<<26&469762048}get underlineColor(){return this._ext&67108863}set underlineColor(e){this._ext&=-67108864,this._ext|=e&67108863}get urlId(){return this._urlId}set urlId(e){this._urlId=e}get underlineVariantOffset(){let e=(this._ext&3758096384)>>29;return e<0?e^4294967288:e}set underlineVariantOffset(e){this._ext&=536870911,this._ext|=e<<29&3758096384}clone(){return new e(this._ext,this._urlId)}isEmpty(){return this.underlineStyle===0&&this._urlId===0}},y=class e extends ue{constructor(){super(...arguments),this.content=0,this.fg=0,this.bg=0,this.extended=new de,this.combinedData=``}static fromCharData(t){let n=new e;return n.setFromCharData(t),n}isCombined(){return this.content&2097152}getWidth(){return this.content>>22}getChars(){return this.content&2097152?this.combinedData:this.content&2097151?ae(this.content&2097151):``}getCode(){return this.isCombined()?this.combinedData.charCodeAt(this.combinedData.length-1):this.content&2097151}setFromCharData(e){this.fg=e[0],this.bg=0;let t=!1;if(e[1].length>2)t=!0;else if(e[1].length===2){let n=e[1].charCodeAt(0);if(55296<=n&&n<=56319){let r=e[1].charCodeAt(1);56320<=r&&r<=57343?this.content=(n-55296)*1024+r-56320+65536|e[2]<<22:t=!0}else t=!0}else this.content=e[1].charCodeAt(0)|e[2]<<22;t&&(this.combinedData=e[1],this.content=2097152|e[2]<<22)}getAsCharData(){return[this.fg,this.getChars(),this.getWidth(),this.getCode()]}},fe=`di$target`,pe=`di$dependencies`,me=new Map;function b(e){return e[pe]||[]}function x(e){if(me.has(e))return me.get(e);let t=function(e,n,r){if(arguments.length!==3)throw Error(`@IServiceName-decorator can only be used to decorate a parameter`);he(t,e,r)};return t._id=e,me.set(e,t),t}function he(e,t,n){t[fe]===t?t[pe].push({id:e,index:n}):(t[pe]=[{id:e,index:n}],t[fe]=t)}var S=x(`BufferService`),ge=x(`CoreMouseService`),_e=x(`CoreService`),C=x(`CharsetService`),ve=x(`InstantiationService`),w=x(`LogService`),T=x(`OptionsService`),ye=x(`OscLinkService`),be=x(`UnicodeService`),xe=x(`DecorationService`),Se=class{constructor(e,t,n){this._bufferService=e,this._optionsService=t,this._oscLinkService=n}provideLinks(e,t){let n=this._bufferService.buffer.lines.get(e-1);if(!n){t(void 0);return}let r=[],i=this._optionsService.rawOptions.linkHandler,a=new y,o=n.getTrimmedLength(),s=-1,c=-1,l=!1;for(let t=0;t<o;t++)if(c!==-1||n.hasContent(t)){if(n.loadCell(t,a),a.hasExtendedAttrs()&&a.extended.urlId){if(c===-1){c=t,s=a.extended.urlId;continue}l=a.extended.urlId!==s}else c!==-1&&(l=!0);if(l||c!==-1&&t===o-1){let n=this._oscLinkService.getLinkData(s)?.uri;if(n){let a={start:{x:c+1,y:e},end:{x:t+ +(!l&&t===o-1),y:e}},s=!1;if(!i?.allowNonHttpProtocols)try{let e=new URL(n);[`http:`,`https:`].includes(e.protocol)||(s=!0)}catch{s=!0}s||r.push({text:n,range:a,activate:(e,t)=>i?i.activate(e,t,a):Ce(e,t),hover:(e,t)=>i?.hover?.(e,t,a),leave:(e,t)=>i?.leave?.(e,t,a)})}l=!1,a.hasExtendedAttrs()&&a.extended.urlId?(c=t,s=a.extended.urlId):(c=-1,s=-1)}}t(r)}};Se=u([d(0,S),d(1,T),d(2,ye)],Se);function Ce(e,t){if(confirm(`Do you want to navigate to ${t}?
2
2
 
3
3
  WARNING: This link could potentially be dangerous`)){let e=window.open();if(e){try{e.opener=null}catch{}e.location.href=t}else console.warn(`Opening link blocked as opener could not be cleared`)}}var we=x(`CharSizeService`),Te=x(`CoreBrowserService`),Ee=x(`MouseService`),De=x(`RenderService`),Oe=x(`SelectionService`),ke=x(`CharacterJoinerService`),Ae=x(`ThemeService`),je=x(`LinkProviderService`),Me=new class{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout(()=>{throw e.stack?Re.isErrorNoTelemetry(e)?new Re(e.message+`
4
4