refactor(coding-agent): narrowed over-exported internal symbols
- 28 symbols across discovery, mcp header policy, agent-hub projection and rendering, the agent registry, shell tokenizing and changelog comparison were exported but referenced only inside their own module; they are now module-private, shrinking the deep-import surface. - Kept AGENT_PLUGIN_MANIFEST_SCHEMA, AGENT_PLUGIN_MCP_SCHEMA, parseAgentPluginManifest, clearAgentPluginRootCache and mergeMCPHeaders exported: each is a seam for tests that defend real parsing or header precedence behavior. - Nothing reachable from an explicit exports entry or public barrel changed.
This commit is contained in:
@@ -74,13 +74,13 @@ export interface AgentPluginManifest {
|
||||
* - `invalid` — the document targets Agent Plugins but violates the closed schema
|
||||
* fatally; the plugin must be rejected and none of its components loaded (spec §5.2).
|
||||
*/
|
||||
export type AgentPluginManifestResult =
|
||||
type AgentPluginManifestResult =
|
||||
| { status: "none" }
|
||||
| { status: "valid"; manifest: AgentPluginManifest; warnings: string[] }
|
||||
| { status: "invalid"; reason: string };
|
||||
|
||||
/** Enforce the plugin `name` constraints from spec §5.5. */
|
||||
export function isValidAgentPluginName(name: string): boolean {
|
||||
function isValidAgentPluginName(name: string): boolean {
|
||||
if (name.length < 1 || name.length > 64) return false;
|
||||
if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/.test(name)) return false;
|
||||
return !name.includes("--") && !name.includes("..");
|
||||
@@ -240,14 +240,14 @@ export function parseAgentPluginManifest(raw: string): AgentPluginManifestResult
|
||||
* (spec §9.2). Single non-recursive pass; replacement text is never rescanned,
|
||||
* and no other placeholder or environment-variable expansion is performed.
|
||||
*/
|
||||
export function expandAgentPluginPlaceholders(value: string, pluginRoot: string, pluginData: string): string {
|
||||
function expandAgentPluginPlaceholders(value: string, pluginRoot: string, pluginData: string): string {
|
||||
return value.replace(/\$\{PLUGIN_(ROOT|DATA)\}/g, (_match, which: string) =>
|
||||
which === "ROOT" ? pluginRoot : pluginData,
|
||||
);
|
||||
}
|
||||
|
||||
/** A validated `mcp.json` server entry, resolved to launch-ready values. */
|
||||
export interface AgentPluginMcpServer {
|
||||
interface AgentPluginMcpServer {
|
||||
name: string;
|
||||
transport: "stdio" | "http" | "sse";
|
||||
/** Absolute path for `./`-relative commands; bare executable token otherwise. */
|
||||
@@ -268,11 +268,11 @@ export interface AgentPluginMcpServer {
|
||||
* - `ok` — the document is valid; individually invalid server entries are
|
||||
* skipped with a warning (spec §7.2.2 rule 3).
|
||||
*/
|
||||
export type AgentPluginMcpResult =
|
||||
type AgentPluginMcpResult =
|
||||
| { status: "disabled"; reason: string }
|
||||
| { status: "ok"; servers: AgentPluginMcpServer[]; warnings: string[] };
|
||||
|
||||
export interface AgentPluginMcpOptions {
|
||||
interface AgentPluginMcpOptions {
|
||||
/** Filesystem-resolved plugin root. */
|
||||
pluginRoot: string;
|
||||
/** Client-managed persistent data directory for this plugin (spec §9.1). */
|
||||
@@ -488,7 +488,7 @@ export async function parseAgentPluginMcp(raw: string, options: AgentPluginMcpOp
|
||||
* - `invalid` — the root claims Agent Plugins conformance but its manifest is
|
||||
* fatally invalid; no component may be discovered or executed (spec §11.3).
|
||||
*/
|
||||
export type AgentPluginRootStatus =
|
||||
type AgentPluginRootStatus =
|
||||
| { kind: "none" }
|
||||
| { kind: "standard"; manifest: AgentPluginManifest; warnings: string[]; realRoot: string }
|
||||
| { kind: "invalid"; reason: string };
|
||||
|
||||
@@ -14,7 +14,7 @@ import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
|
||||
/** Lexical containment: `target` is `base` itself or a descendant of it. */
|
||||
export function isContained(base: string, target: string): boolean {
|
||||
function isContained(base: string, target: string): boolean {
|
||||
const relative = path.relative(base, target);
|
||||
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
||||
}
|
||||
@@ -29,10 +29,7 @@ export async function realpathIfExists(p: string): Promise<string | null> {
|
||||
}
|
||||
|
||||
/** Outcome of resolving a fixed package path without reading it. */
|
||||
export type ContainedPathResolution =
|
||||
| { status: "missing" }
|
||||
| { status: "outside" }
|
||||
| { status: "ok"; realPath: string };
|
||||
type ContainedPathResolution = { status: "missing" } | { status: "outside" } | { status: "ok"; realPath: string };
|
||||
|
||||
/**
|
||||
* Resolve a fixed package path WITHOUT reading it: symlinks and equivalent
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
/** Header buckets for one MCP HTTP request. */
|
||||
export interface MCPHeaderSources {
|
||||
interface MCPHeaderSources {
|
||||
/** Client-generated HTTP/MCP/authorization headers; win case-insensitively. */
|
||||
generated: Record<string, string>;
|
||||
/** Configured headers from the server entry (package or user config). */
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface AggregateMetrics extends AgentMetrics {
|
||||
activeDurationAgents: number;
|
||||
}
|
||||
|
||||
export interface AgentTreeProjection {
|
||||
interface AgentTreeProjection {
|
||||
rows: AgentRef[];
|
||||
depthById: Map<string, number>;
|
||||
parentById: Map<string, string>;
|
||||
@@ -65,7 +65,7 @@ export function progressMetrics(observed: ObservableSession | undefined): AgentM
|
||||
* usage embedded in completed `task` tool results, so using it for a parent
|
||||
* row would double-count child rows in the aggregate.
|
||||
*/
|
||||
export function readSessionMetrics(session: NonNullable<AgentRef["session"]>): AgentMetrics | undefined {
|
||||
function readSessionMetrics(session: NonNullable<AgentRef["session"]>): AgentMetrics | undefined {
|
||||
try {
|
||||
const stats = session.getSessionStats();
|
||||
const messages = session.agent?.state?.messages;
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface RosterRender {
|
||||
}
|
||||
|
||||
/** Legacy progress snapshots may omit counters; snapshot absence remains distinct. */
|
||||
export function metricNumber(value: number | undefined): number {
|
||||
function metricNumber(value: number | undefined): number {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ export function statusText(status: AgentRef["status"], text: string): string {
|
||||
}
|
||||
|
||||
/** Model id + thinking level (`sonnet-4-6 ◒ high`), level colored per theme. */
|
||||
export function formatModelBadge(modelId: string, level: ThinkingLevel | undefined): string {
|
||||
function formatModelBadge(modelId: string, level: ThinkingLevel | undefined): string {
|
||||
const model = theme.fg("muted", sanitizeDisplayText(modelId));
|
||||
if (!level || level === ThinkingLevel.Off || level === ThinkingLevel.Inherit) return model;
|
||||
const display = theme.thinking[level as keyof typeof theme.thinking] ?? level;
|
||||
@@ -81,11 +81,7 @@ export function formatRoleBadge(role: string, settings: Settings): string {
|
||||
}
|
||||
|
||||
/** Format a resolved selector, preserving provider identity when requested. */
|
||||
export function formatResolvedModelBadge(
|
||||
resolved: string,
|
||||
preserveProvider = false,
|
||||
fallbackLevel?: ThinkingLevel,
|
||||
): string {
|
||||
function formatResolvedModelBadge(resolved: string, preserveProvider = false, fallbackLevel?: ThinkingLevel): string {
|
||||
const cleanResolved = sanitizeDisplayText(resolved);
|
||||
// Model ids may themselves contain colons (`qwen3:14b`), so only treat the
|
||||
// suffix as a thinking level when it parses as one.
|
||||
|
||||
@@ -15,7 +15,7 @@ import { oneLineLabel } from "../task/types";
|
||||
export const MAIN_AGENT_ID = "Main";
|
||||
|
||||
/** Sidecar marker retained beside a child transcript after an explicit kill. */
|
||||
export const AGENT_TOMBSTONE_SUFFIX = ".tombstone";
|
||||
const AGENT_TOMBSTONE_SUFFIX = ".tombstone";
|
||||
|
||||
export function getAgentTombstonePath(sessionFile: string): string {
|
||||
return `${sessionFile}${AGENT_TOMBSTONE_SUFFIX}`;
|
||||
@@ -30,7 +30,7 @@ export function getAgentTombstonePath(sessionFile: string): string {
|
||||
*/
|
||||
export type AgentStatus = "running" | "idle" | "parked" | "aborted";
|
||||
/** Provenance of a displayed duration: active runtime, transcript span, or unavailable. */
|
||||
export type AgentDurationKind = "active" | "span" | "unknown";
|
||||
type AgentDurationKind = "active" | "span" | "unknown";
|
||||
/**
|
||||
* - `main`/`sub`: the user-facing agent tree (driving agent + task subagents).
|
||||
* - `advisor`: a passive review transcript persisted like a subagent for usage
|
||||
|
||||
@@ -87,7 +87,7 @@ export function tokenizeShellSegments(command: string): string[][] {
|
||||
*
|
||||
* @see extractFlatShellCommandSegments
|
||||
*/
|
||||
export interface FlatShellCommandSegment {
|
||||
interface FlatShellCommandSegment {
|
||||
/** Original segment text with quoting and escaping preserved. */
|
||||
text: string;
|
||||
/**
|
||||
|
||||
@@ -201,7 +201,7 @@ function parseChangelogContent(content: string): ChangelogEntry[] {
|
||||
* Compare changelog entries by their parsed version parts.
|
||||
* Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
||||
*/
|
||||
export function compareChangelogEntries(v1: ChangelogEntry, v2: ChangelogEntry): number {
|
||||
function compareChangelogEntries(v1: ChangelogEntry, v2: ChangelogEntry): number {
|
||||
if (v1.major !== v2.major) return v1.major - v2.major;
|
||||
if (v1.minor !== v2.minor) return v1.minor - v2.minor;
|
||||
return v1.patch - v2.patch;
|
||||
|
||||
Reference in New Issue
Block a user