Merge branch 'main' into stream-fn-in-compaction

This commit is contained in:
Mario Zechner
2026-05-17 20:59:53 +02:00
committed by GitHub
36 changed files with 396 additions and 343 deletions

View File

@@ -5,7 +5,7 @@
*
* Test with: npx tsx src/cli-new.ts [args...]
*/
import { EnvHttpProxyAgent, setGlobalDispatcher, fetch as undiciFetch } from "undici";
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
import { APP_NAME } from "./config.js";
import { main } from "./main.js";
@@ -17,15 +17,6 @@ process.emitWarning = (() => {}) as typeof process.emitWarning;
// (e.g. vLLM buffering a large tool call) exceed that and abort the SSE stream
// with UND_ERR_BODY_TIMEOUT. Disable both — provider SDKs enforce their own
// AbortController-based deadlines via retry.provider.timeoutMs.
// Node 26 uses an internal undici for globalThis.fetch that does not honor npm
// undici's global dispatcher, so route global fetch through npm undici as well.
const dispatcher = new EnvHttpProxyAgent({ bodyTimeout: 0, headersTimeout: 0 });
setGlobalDispatcher(dispatcher);
const fetchWithDispatcher = undiciFetch as unknown as typeof fetch;
globalThis.fetch = (input, init) =>
fetchWithDispatcher(input, {
...init,
dispatcher,
} as unknown as RequestInit);
setGlobalDispatcher(new EnvHttpProxyAgent({ bodyTimeout: 0, headersTimeout: 0 }));
main(process.argv.slice(2));

View File

@@ -1084,7 +1084,7 @@ export class DefaultPackageManager implements PackageManager {
}
private async shouldUpdateNpmSource(source: NpmSource, scope: InstalledSourceScope): Promise<boolean> {
const installedPath = this.getNpmInstallPath(source, scope);
const installedPath = this.getManagedNpmInstallPath(source, scope);
const installedVersion = existsSync(installedPath) ? this.getInstalledNpmVersion(installedPath) : undefined;
if (!installedVersion) {
return true;
@@ -1114,13 +1114,9 @@ export class DefaultPackageManager implements PackageManager {
}
private async installNpmBatch(specs: string[], scope: InstalledSourceScope): Promise<void> {
if (scope === "user") {
await this.runNpmCommand(["install", "-g", ...specs]);
return;
}
const installRoot = this.getNpmInstallRoot(scope, false);
this.ensureNpmProject(installRoot);
await this.runNpmCommand(["install", ...specs, "--prefix", installRoot]);
await this.runNpmCommand(this.getNpmInstallArgs(specs, installRoot));
}
async checkForAvailableUpdates(): Promise<PackageUpdate[]> {
@@ -1669,6 +1665,14 @@ export class DefaultPackageManager implements PackageManager {
return { command, args };
}
private getPackageManagerName(): string {
const npmCommand = this.getNpmCommand();
const commandParts = [npmCommand.command, ...npmCommand.args];
const separatorIndex = commandParts.lastIndexOf("--");
const packageManagerCommand = separatorIndex >= 0 ? commandParts[separatorIndex + 1] : npmCommand.command;
return packageManagerCommand ? basename(packageManagerCommand).replace(/\.(cmd|exe)$/i, "") : "";
}
private async runNpmCommand(args: string[], options?: { cwd?: string }): Promise<void> {
const npmCommand = this.getNpmCommand();
await this.runCommand(npmCommand.command, [...npmCommand.args, ...args], options);
@@ -1687,25 +1691,32 @@ export class DefaultPackageManager implements PackageManager {
return this.runCommandSync(npmCommand.command, [...npmCommand.args, ...args]);
}
private async installNpm(source: NpmSource, scope: SourceScope, temporary: boolean): Promise<void> {
if (scope === "user" && !temporary) {
await this.runNpmCommand(["install", "-g", source.spec]);
return;
private getNpmInstallArgs(specs: string[], installRoot: string): string[] {
const packageManagerName = this.getPackageManagerName();
if (packageManagerName === "bun") {
return ["install", ...specs, "--cwd", installRoot];
}
if (packageManagerName === "pnpm") {
return ["install", ...specs, "--prefix", installRoot, "--config.strict-dep-builds=false"];
}
return ["install", ...specs, "--prefix", installRoot];
}
private async installNpm(source: NpmSource, scope: SourceScope, temporary: boolean): Promise<void> {
const installRoot = this.getNpmInstallRoot(scope, temporary);
this.ensureNpmProject(installRoot);
await this.runNpmCommand(["install", source.spec, "--prefix", installRoot]);
await this.runNpmCommand(this.getNpmInstallArgs([source.spec], installRoot));
}
private async uninstallNpm(source: NpmSource, scope: SourceScope): Promise<void> {
if (scope === "user") {
await this.runNpmCommand(["uninstall", "-g", source.name]);
return;
}
const installRoot = this.getNpmInstallRoot(scope, false);
if (!existsSync(installRoot)) {
return;
}
if (this.getPackageManagerName() === "bun") {
await this.runNpmCommand(["uninstall", source.name, "--cwd", installRoot]);
return;
}
await this.runNpmCommand(["uninstall", source.name, "--prefix", installRoot]);
}
@@ -1836,7 +1847,7 @@ export class DefaultPackageManager implements PackageManager {
if (scope === "project") {
return join(this.cwd, CONFIG_DIR_NAME, "npm");
}
return join(this.getGlobalNpmRoot(), "..");
return join(this.agentDir, "npm");
}
private getGlobalNpmRoot(): string {
@@ -1845,8 +1856,7 @@ export class DefaultPackageManager implements PackageManager {
if (this.globalNpmRoot && this.globalNpmRootCommandKey === commandKey) {
return this.globalNpmRoot;
}
const isBunPackageManager = npmCommand.command === "bun";
if (isBunPackageManager) {
if (this.getPackageManagerName() === "bun") {
const binDir = this.runNpmCommandSync(["pm", "bin", "-g"]).trim();
this.globalNpmRoot = join(dirname(binDir), "install", "global", "node_modules");
} else {
@@ -1857,14 +1867,7 @@ export class DefaultPackageManager implements PackageManager {
}
private getPnpmGlobalPackagePath(packageName: string): string | undefined {
const npmCommand = this.getNpmCommand();
const commandParts = [npmCommand.command, ...npmCommand.args];
const separatorIndex = commandParts.lastIndexOf("--");
const packageManagerCommand = separatorIndex >= 0 ? commandParts[separatorIndex + 1] : npmCommand.command;
const packageManagerName = packageManagerCommand
? basename(packageManagerCommand).replace(/\.(cmd|exe)$/i, "")
: "";
if (packageManagerName !== "pnpm") {
if (this.getPackageManagerName() !== "pnpm") {
return undefined;
}
@@ -1877,14 +1880,31 @@ export class DefaultPackageManager implements PackageManager {
return undefined;
}
private getNpmInstallPath(source: NpmSource, scope: SourceScope): string {
private getManagedNpmInstallPath(source: NpmSource, scope: SourceScope): string {
if (scope === "temporary") {
return join(this.getTemporaryDir("npm"), "node_modules", source.name);
}
if (scope === "project") {
return join(this.cwd, CONFIG_DIR_NAME, "npm", "node_modules", source.name);
}
return this.getPnpmGlobalPackagePath(source.name) ?? join(this.getGlobalNpmRoot(), source.name);
return join(this.agentDir, "npm", "node_modules", source.name);
}
private getLegacyGlobalNpmInstallPath(source: NpmSource): string | undefined {
try {
return this.getPnpmGlobalPackagePath(source.name) ?? join(this.getGlobalNpmRoot(), source.name);
} catch {
return undefined;
}
}
private getNpmInstallPath(source: NpmSource, scope: SourceScope): string {
const managedPath = this.getManagedNpmInstallPath(source, scope);
if (scope !== "user" || existsSync(managedPath)) {
return managedPath;
}
const legacyPath = this.getLegacyGlobalNpmInstallPath(source);
return legacyPath && existsSync(legacyPath) ? legacyPath : managedPath;
}
private getGitInstallPath(source: GitSource, scope: SourceScope): string {

View File

@@ -59,11 +59,12 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions): string {
// Append project context files
if (contextFiles.length > 0) {
prompt += "\n\n# Project Context\n\n";
prompt += "\n\n<project_context>\n\n";
prompt += "Project-specific instructions and guidelines:\n\n";
for (const { path: filePath, content } of contextFiles) {
prompt += `## ${filePath}\n\n${content}\n\n`;
prompt += `<project_instructions path="${filePath}">\n${content}\n</project_instructions>\n\n`;
}
prompt += "</project_context>\n";
}
// Append skills section (only if read tool is available)