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:
Mario Zechner
2026-04-03 20:14:12 +02:00
parent 042066b982
commit 9f9277ccdd
38 changed files with 2180 additions and 1366 deletions

View File

@@ -57,11 +57,21 @@ export interface PackageUpdate {
scope: Exclude<SourceScope, "temporary">;
}
export interface ConfiguredPackage {
source: string;
scope: "user" | "project";
filtered: boolean;
installedPath?: string;
}
export interface PackageManager {
resolve(onMissing?: (source: string) => Promise<MissingSourceAction>): Promise<ResolvedPaths>;
install(source: string, options?: { local?: boolean }): Promise<void>;
installAndPersist(source: string, options?: { local?: boolean }): Promise<void>;
remove(source: string, options?: { local?: boolean }): Promise<void>;
removeAndPersist(source: string, options?: { local?: boolean }): Promise<boolean>;
update(source?: string): Promise<void>;
listConfiguredPackages(): ConfiguredPackage[];
resolveExtensionSources(
sources: string[],
options?: { local?: boolean; temporary?: boolean },
@@ -837,6 +847,34 @@ export class DefaultPackageManager implements PackageManager {
return this.toResolvedPaths(accumulator);
}
listConfiguredPackages(): ConfiguredPackage[] {
const globalSettings = this.settingsManager.getGlobalSettings();
const projectSettings = this.settingsManager.getProjectSettings();
const configuredPackages: ConfiguredPackage[] = [];
for (const pkg of globalSettings.packages ?? []) {
const source = typeof pkg === "string" ? pkg : pkg.source;
configuredPackages.push({
source,
scope: "user",
filtered: typeof pkg === "object",
installedPath: this.getInstalledPath(source, "user"),
});
}
for (const pkg of projectSettings.packages ?? []) {
const source = typeof pkg === "string" ? pkg : pkg.source;
configuredPackages.push({
source,
scope: "project",
filtered: typeof pkg === "object",
installedPath: this.getInstalledPath(source, "project"),
});
}
return configuredPackages;
}
async install(source: string, options?: { local?: boolean }): Promise<void> {
const parsed = this.parseSource(source);
const scope: SourceScope = options?.local ? "project" : "user";
@@ -860,6 +898,11 @@ export class DefaultPackageManager implements PackageManager {
});
}
async installAndPersist(source: string, options?: { local?: boolean }): Promise<void> {
await this.install(source, options);
this.addSourceToSettings(source, options);
}
async remove(source: string, options?: { local?: boolean }): Promise<void> {
const parsed = this.parseSource(source);
const scope: SourceScope = options?.local ? "project" : "user";
@@ -879,6 +922,11 @@ export class DefaultPackageManager implements PackageManager {
});
}
async removeAndPersist(source: string, options?: { local?: boolean }): Promise<boolean> {
await this.remove(source, options);
return this.removeSourceFromSettings(source, options);
}
async update(source?: string): Promise<void> {
const globalSettings = this.settingsManager.getGlobalSettings();
const projectSettings = this.settingsManager.getProjectSettings();