refactor(coding-agent): replace AgentSessionRuntimeHost with closure-based AgentSessionRuntime
- Replace AgentSessionRuntimeHost and bootstrap abstractions with AgentSessionRuntime - Runtime creation is now closure-based via CreateAgentSessionRuntimeFactory - Factory closes over process-global fixed inputs, recreates cwd-bound services per effective cwd - Session config (model, thinking, tools, scoped models) re-resolved per target cwd - CLI resource paths resolved once at startup as absolute paths - Swap lifecycle: teardown old, create next, apply next (hard fail on creation error) - Unified diagnostics model (info/warning/error) for args, services, session resolution, resources - No logging or process exits inside creation/parsing logic - Removed session_directory support - Removed session_switch and session_fork extension events (use session_start with reason) - Moved package/config CLI to package-manager-cli.ts - Fixed theme init for --resume session picker - Fixed flaky reftable footer test (content-based polling) - Fixed silent drop of unknown single-dash CLI flags - Added error diagnostics for missing explicit CLI resource paths - Updated SDK docs, examples, plans, exports, tests, changelog fixes #2753
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
|
||||
import chalk from "chalk";
|
||||
import { APP_NAME, CONFIG_DIR_NAME, ENV_AGENT_DIR } from "../config.js";
|
||||
import type { ExtensionFlag } from "../core/extensions/types.js";
|
||||
import { allTools, type ToolName } from "../core/tools/index.js";
|
||||
|
||||
export type Mode = "text" | "json" | "rpc";
|
||||
@@ -45,6 +46,7 @@ export interface Args {
|
||||
fileArgs: string[];
|
||||
/** Unknown flags (potentially extension flags) - map of flag name to value */
|
||||
unknownFlags: Map<string, boolean | string>;
|
||||
diagnostics: Array<{ type: "warning" | "error"; message: string }>;
|
||||
}
|
||||
|
||||
const VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const;
|
||||
@@ -53,11 +55,12 @@ export function isValidThinkingLevel(level: string): level is ThinkingLevel {
|
||||
return VALID_THINKING_LEVELS.includes(level as ThinkingLevel);
|
||||
}
|
||||
|
||||
export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "boolean" | "string" }>): Args {
|
||||
export function parseArgs(args: string[]): Args {
|
||||
const result: Args = {
|
||||
messages: [],
|
||||
fileArgs: [],
|
||||
unknownFlags: new Map(),
|
||||
diagnostics: [],
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
@@ -105,9 +108,10 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
||||
if (name in allTools) {
|
||||
validTools.push(name as ToolName);
|
||||
} else {
|
||||
console.error(
|
||||
chalk.yellow(`Warning: Unknown tool "${name}". Valid tools: ${Object.keys(allTools).join(", ")}`),
|
||||
);
|
||||
result.diagnostics.push({
|
||||
type: "warning",
|
||||
message: `Unknown tool "${name}". Valid tools: ${Object.keys(allTools).join(", ")}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
result.tools = validTools;
|
||||
@@ -116,11 +120,10 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
||||
if (isValidThinkingLevel(level)) {
|
||||
result.thinking = level;
|
||||
} else {
|
||||
console.error(
|
||||
chalk.yellow(
|
||||
`Warning: Invalid thinking level "${level}". Valid values: ${VALID_THINKING_LEVELS.join(", ")}`,
|
||||
),
|
||||
);
|
||||
result.diagnostics.push({
|
||||
type: "warning",
|
||||
message: `Invalid thinking level "${level}". Valid values: ${VALID_THINKING_LEVELS.join(", ")}`,
|
||||
});
|
||||
}
|
||||
} else if (arg === "--print" || arg === "-p") {
|
||||
result.print = true;
|
||||
@@ -159,18 +162,22 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
||||
result.offline = true;
|
||||
} else if (arg.startsWith("@")) {
|
||||
result.fileArgs.push(arg.slice(1)); // Remove @ prefix
|
||||
} else if (arg.startsWith("--") && extensionFlags) {
|
||||
// Check if it's an extension-registered flag
|
||||
const flagName = arg.slice(2);
|
||||
const extFlag = extensionFlags.get(flagName);
|
||||
if (extFlag) {
|
||||
if (extFlag.type === "boolean") {
|
||||
} else if (arg.startsWith("--")) {
|
||||
const eqIndex = arg.indexOf("=");
|
||||
if (eqIndex !== -1) {
|
||||
result.unknownFlags.set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1));
|
||||
} else {
|
||||
const flagName = arg.slice(2);
|
||||
const next = args[i + 1];
|
||||
if (next !== undefined && !next.startsWith("-") && !next.startsWith("@")) {
|
||||
result.unknownFlags.set(flagName, next);
|
||||
i++;
|
||||
} else {
|
||||
result.unknownFlags.set(flagName, true);
|
||||
} else if (extFlag.type === "string" && i + 1 < args.length) {
|
||||
result.unknownFlags.set(flagName, args[++i]);
|
||||
}
|
||||
}
|
||||
// Unknown flags without extensionFlags are silently ignored (first pass)
|
||||
} else if (arg.startsWith("-") && !arg.startsWith("--")) {
|
||||
result.diagnostics.push({ type: "error", message: `Unknown option: ${arg}` });
|
||||
} else if (!arg.startsWith("-")) {
|
||||
result.messages.push(arg);
|
||||
}
|
||||
@@ -179,7 +186,17 @@ export function parseArgs(args: string[], extensionFlags?: Map<string, { type: "
|
||||
return result;
|
||||
}
|
||||
|
||||
export function printHelp(): void {
|
||||
export function printHelp(extensionFlags?: ExtensionFlag[]): void {
|
||||
const extensionFlagsText =
|
||||
extensionFlags && extensionFlags.length > 0
|
||||
? `\n${chalk.bold("Extension CLI Flags:")}\n${extensionFlags
|
||||
.map((flag) => {
|
||||
const value = flag.type === "string" ? " <value>" : "";
|
||||
const description = flag.description ?? `Registered by ${flag.extensionPath}`;
|
||||
return ` --${flag.name}${value}`.padEnd(30) + description;
|
||||
})
|
||||
.join("\n")}\n`
|
||||
: "";
|
||||
console.log(`${chalk.bold(APP_NAME)} - AI coding assistant with read, bash, edit, write tools
|
||||
|
||||
${chalk.bold("Usage:")}
|
||||
@@ -229,7 +246,7 @@ ${chalk.bold("Options:")}
|
||||
--help, -h Show this help
|
||||
--version, -v Show version number
|
||||
|
||||
Extensions can register additional flags (e.g., --plan from plan-mode extension).
|
||||
Extensions can register additional flags (e.g., --plan from plan-mode extension).${extensionFlagsText}
|
||||
|
||||
${chalk.bold("Examples:")}
|
||||
# Interactive mode
|
||||
|
||||
Reference in New Issue
Block a user