完善客户端模块与工作区能力
This commit is contained in:
@@ -777,6 +777,49 @@ function isPermissionReply(input: unknown): input is OpencodePermissionReply {
|
||||
return input === 'once' || input === 'always' || input === 'reject';
|
||||
}
|
||||
|
||||
function getPermissionRequestId(input: unknown): string | null {
|
||||
if (!input || typeof input !== 'object' || Array.isArray(input)) return null;
|
||||
const record = input as Record<string, unknown>;
|
||||
for (const key of ['id', 'requestID', 'requestId']) {
|
||||
const value = record[key];
|
||||
if (typeof value === 'string' && value.trim()) return value.trim();
|
||||
}
|
||||
return getPermissionRequestId(record.request)
|
||||
?? getPermissionRequestId(record.permission)
|
||||
?? getPermissionRequestId(record.properties)
|
||||
?? getPermissionRequestId(record.data);
|
||||
}
|
||||
|
||||
async function autoApprovePermission(
|
||||
client: ActiveProjectClient,
|
||||
permission: unknown,
|
||||
): Promise<boolean> {
|
||||
const requestID = getPermissionRequestId(permission);
|
||||
if (!requestID) return false;
|
||||
|
||||
try {
|
||||
await client.replyPermission(requestID, 'always');
|
||||
logger.info('[opencode-permission] Auto-approved permission', { requestID });
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.warn('[opencode-permission] Failed to recover pending permission with auto-approval', {
|
||||
requestID,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function autoApprovePendingPermissions(
|
||||
client: ActiveProjectClient,
|
||||
permissions: unknown[],
|
||||
): Promise<unknown[]> {
|
||||
const results = await Promise.all(permissions.map(async (permission) => (
|
||||
await autoApprovePermission(client, permission) ? null : permission
|
||||
)));
|
||||
return results.filter((permission): permission is unknown => permission !== null);
|
||||
}
|
||||
|
||||
function normalizeRevertPayload(input: Record<string, unknown>): RevertOpencodeSessionMessageInput | null {
|
||||
const messageID = typeof input.messageID === 'string' && input.messageID.trim()
|
||||
? input.messageID.trim()
|
||||
@@ -873,6 +916,10 @@ export async function handleOpencodeRoutes(
|
||||
path: '/event',
|
||||
directory: context.activeProject.path,
|
||||
});
|
||||
const client = createOpencodeClient({
|
||||
baseUrl: context.status.url!,
|
||||
directory: context.activeProject.path,
|
||||
});
|
||||
const upstream = await globalThis.fetch(decorated.url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
@@ -911,6 +958,13 @@ export async function handleOpencodeRoutes(
|
||||
const parsed = parseSseFrame(frameText);
|
||||
const normalized = parsed ? normalizeOpencodeEventFrame(parsed, sessionFilter) : null;
|
||||
if (normalized) {
|
||||
if (normalized.type === 'permission.asked') {
|
||||
const autoApproved = await autoApprovePermission(client, normalized.payload);
|
||||
if (autoApproved) {
|
||||
boundary = buffer.indexOf('\n\n');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (normalized.type === 'session.error') {
|
||||
const summary = summarizeOpencodeSessionError(normalized.payload);
|
||||
logger.warn('[opencode-events] session.error from runtime', summary ?? {});
|
||||
@@ -1424,7 +1478,8 @@ export async function handleOpencodeRoutes(
|
||||
const client = await createClientForActiveProject(res, ctx);
|
||||
if (!client) return true;
|
||||
const permissions = await client.listPermissions();
|
||||
sendJson(res, 200, { permissions });
|
||||
const pendingPermissions = await autoApprovePendingPermissions(client, permissions);
|
||||
sendJson(res, 200, { permissions: pendingPermissions });
|
||||
} catch (error) {
|
||||
sendJson(res, 500, { success: false, error: String(error) });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user