fix: restore agent mentions and child permission auto-accept
Sends tagged agents as OpenCode agent parts Auto-accepts pending child-session permissions from parent sessions
This commit is contained in:
@@ -107,14 +107,13 @@ const normalizeDirectoryCandidate = (value: unknown): string | null => {
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
};
|
||||
|
||||
const collectPendingFromSyncStores = (sessionScope: Set<string>): Array<{ id: string; sessionID: string }> => {
|
||||
const collectPendingFromSyncStores = (): Array<{ id: string; sessionID: string }> => {
|
||||
try {
|
||||
const stores = getSyncChildStores();
|
||||
const pending: Array<{ id: string; sessionID: string }> = [];
|
||||
for (const store of stores.children.values()) {
|
||||
const permissionMap = store.getState().permission ?? {};
|
||||
for (const [sessionId, entries] of Object.entries(permissionMap)) {
|
||||
if (!sessionScope.has(sessionId)) continue;
|
||||
for (const permission of entries ?? []) {
|
||||
if (!permission?.id) continue;
|
||||
pending.push({ id: permission.id, sessionID: permission.sessionID || sessionId });
|
||||
@@ -127,6 +126,68 @@ const collectPendingFromSyncStores = (sessionScope: Set<string>): Array<{ id: st
|
||||
}
|
||||
};
|
||||
|
||||
const sessionBelongsToScope = async (
|
||||
sessionID: string,
|
||||
rootSessionID: string,
|
||||
knownSessions: Session[],
|
||||
directories: string[],
|
||||
): Promise<boolean> => {
|
||||
if (sessionID === rootSessionID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const knownById = new Map<string, Session>();
|
||||
for (const session of knownSessions) {
|
||||
knownById.set(session.id, session);
|
||||
}
|
||||
|
||||
const fetchedById = new Map<string, Session>();
|
||||
const fetchSession = async (id: string): Promise<Session | null> => {
|
||||
const known = knownById.get(id) ?? fetchedById.get(id);
|
||||
if (known) return known;
|
||||
|
||||
for (const directory of directories) {
|
||||
try {
|
||||
const result = await opencodeClient.getScopedSdkClient(directory).session.get({
|
||||
sessionID: id,
|
||||
directory,
|
||||
});
|
||||
if (result.data) {
|
||||
fetchedById.set(id, result.data);
|
||||
return result.data;
|
||||
}
|
||||
} catch {
|
||||
// Try the next known project directory.
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await opencodeClient.getSdkClient().session.get({ sessionID: id });
|
||||
if (result.data) {
|
||||
fetchedById.set(id, result.data);
|
||||
return result.data;
|
||||
}
|
||||
} catch {
|
||||
// Missing session metadata means we cannot safely inherit the parent setting.
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const seen = new Set<string>();
|
||||
let current: string | undefined = sessionID;
|
||||
while (current && !seen.has(current)) {
|
||||
if (current === rootSessionID) {
|
||||
return true;
|
||||
}
|
||||
seen.add(current);
|
||||
const session = await fetchSession(current);
|
||||
current = session?.parentID ?? undefined;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const autoRespondsPermissionBySession = (
|
||||
autoAccept: PermissionAutoAcceptMap,
|
||||
sessions: Session[],
|
||||
@@ -204,19 +265,29 @@ export const usePermissionStore = create<PermissionStore>()(
|
||||
}
|
||||
}
|
||||
|
||||
const pendingFromStores = collectPendingFromSyncStores(sessionScope);
|
||||
const directoryList = Array.from(directories);
|
||||
const pendingFromStores = collectPendingFromSyncStores();
|
||||
const pendingFromApi = await opencodeClient.listPendingPermissions({ directories: Array.from(directories) });
|
||||
const mergedPending = new Map<string, { id: string; sessionID: string }>();
|
||||
|
||||
for (const permission of pendingFromStores) {
|
||||
mergedPending.set(permission.id, permission);
|
||||
if (sessionScope.has(permission.sessionID)) {
|
||||
mergedPending.set(permission.id, permission);
|
||||
continue;
|
||||
}
|
||||
if (await sessionBelongsToScope(permission.sessionID, sessionId, sessions, directoryList)) {
|
||||
mergedPending.set(permission.id, permission);
|
||||
}
|
||||
}
|
||||
for (const permission of pendingFromApi) {
|
||||
if (!permission?.id || !permission?.sessionID) {
|
||||
continue;
|
||||
}
|
||||
if (!sessionScope.has(permission.sessionID)) {
|
||||
continue;
|
||||
const belongsToScope = await sessionBelongsToScope(permission.sessionID, sessionId, sessions, directoryList);
|
||||
if (!belongsToScope) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mergedPending.set(permission.id, { id: permission.id, sessionID: permission.sessionID });
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ function routeMessage(params: {
|
||||
providerID: string
|
||||
modelID: string
|
||||
agent?: string
|
||||
agentMentionName?: string
|
||||
variant?: string
|
||||
inputMode?: "normal" | "shell"
|
||||
files?: Array<{ type: "file"; mime: string; url: string; filename: string }>
|
||||
@@ -133,6 +134,7 @@ function routeMessage(params: {
|
||||
modelID: params.modelID,
|
||||
text: params.content,
|
||||
agent: params.agent,
|
||||
agentMentions: params.agentMentionName ? [{ name: params.agentMentionName }] : undefined,
|
||||
variant: params.variant,
|
||||
files: params.files,
|
||||
additionalParts: params.additionalParts,
|
||||
@@ -785,6 +787,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
|
||||
providerID,
|
||||
modelID,
|
||||
agent: effectiveDraftAgent,
|
||||
agentMentionName,
|
||||
variant,
|
||||
inputMode,
|
||||
files,
|
||||
@@ -860,6 +863,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
|
||||
providerID,
|
||||
modelID,
|
||||
agent: effectiveAgent,
|
||||
agentMentionName,
|
||||
variant,
|
||||
inputMode,
|
||||
files,
|
||||
|
||||
Reference in New Issue
Block a user