fix(coding-agent): avoid project trust prompt for update (#5674)

This commit is contained in:
Armin Ronacher
2026-06-12 23:37:16 +02:00
committed by GitHub
parent a7cdc679e7
commit b4bff7f0d0
15 changed files with 185 additions and 125 deletions

View File

@@ -3,7 +3,7 @@ import type { LoadExtensionsResult, ProjectTrustContext } from "./extensions/typ
import type { DefaultProjectTrust } from "./settings-manager.ts";
import {
getProjectTrustOptions,
hasProjectTrustInputs,
hasTrustRequiringProjectResources,
type ProjectTrustOption,
type ProjectTrustStore,
} from "./trust-manager.ts";
@@ -46,7 +46,7 @@ export async function resolveProjectTrusted(options: ResolveProjectTrustedOption
if (options.trustOverride !== undefined) {
return options.trustOverride;
}
if (!hasProjectTrustInputs(options.cwd)) {
if (!hasTrustRequiringProjectResources(options.cwd)) {
return true;
}

View File

@@ -1,4 +1,5 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { dirname, join } from "node:path";
import lockfile from "proper-lockfile";
import { CONFIG_DIR_NAME } from "../config.ts";
@@ -25,6 +26,16 @@ export interface ProjectTrustOption {
type TrustFile = Record<string, boolean | null | undefined>;
const TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES = [
"settings.json",
"extensions",
"skills",
"prompts",
"themes",
"SYSTEM.md",
"APPEND_SYSTEM.md",
] as const;
function normalizeCwd(cwd: string): string {
return canonicalizePath(resolvePath(cwd));
}
@@ -45,18 +56,14 @@ function findNearestTrustEntry(data: TrustFile, cwd: string): ProjectTrustStoreE
}
}
export function getProjectTrustPath(cwd: string): string {
return normalizeCwd(cwd);
}
export function getProjectTrustParentPath(cwd: string): string | undefined {
const trustPath = getProjectTrustPath(cwd);
const trustPath = normalizeCwd(cwd);
const parentDir = dirname(trustPath);
return parentDir === trustPath ? undefined : parentDir;
}
export function getProjectTrustOptions(cwd: string, options?: { includeSessionOnly?: boolean }): ProjectTrustOption[] {
const trustPath = getProjectTrustPath(cwd);
const trustPath = normalizeCwd(cwd);
const trustOptions: ProjectTrustOption[] = [
{ label: "Trust", trusted: true, updates: [{ path: trustPath, decision: true }], savedPath: trustPath },
];
@@ -167,18 +174,26 @@ function withTrustFileLock<T>(path: string, fn: () => T): T {
}
}
export function hasProjectConfigDir(cwd: string): boolean {
return existsSync(join(canonicalizePath(resolvePath(cwd)), CONFIG_DIR_NAME));
}
export function hasProjectTrustInputs(cwd: string): boolean {
/**
* Returns true when cwd has project-local resources that must be gated by
* project trust: trust-requiring entries under cwd/.pi, or .agents/skills in
* cwd or one of its ancestors. Returns false when no such project resources
* exist. The user/global ~/.agents/skills directory is always treated as a
* trusted user resource and is ignored here, even when cwd is $HOME.
*/
export function hasTrustRequiringProjectResources(cwd: string): boolean {
const homeDir = canonicalizePath(resolvePath(process.env.HOME || homedir()));
const userAgentsSkillsDir = join(homeDir, ".agents", "skills");
let currentDir = canonicalizePath(resolvePath(cwd));
if (hasProjectConfigDir(currentDir)) {
const configDir = join(currentDir, CONFIG_DIR_NAME);
if (TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some((entry) => existsSync(join(configDir, entry)))) {
return true;
}
while (true) {
if (existsSync(join(currentDir, ".agents", "skills"))) {
const agentsSkillsDir = join(currentDir, ".agents", "skills");
if (agentsSkillsDir !== userAgentsSkillsDir && existsSync(agentsSkillsDir)) {
return true;
}