mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-08 01:43:07 +00:00
* feat(codex): expose Approve for me as a permission mode (#2016) Add autoReview to the Codex permission catalog. It keeps the workspace-write sandbox with on-request approvals and routes escalations to Codex's native reviewer (approvals_reviewer = "auto_review"), the same config as `hapi codex --approve-for-me`. It works at launch and mid-session via thread/settings/update; explicit modes now reset the reviewer to user, and sessions report autoReview from the native reviewer setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(native): expect Auto-review in the Codex permission lists (#2016) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(modes): label autoReview as Auto, matching Claude's auto mode (#2016) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
60a4971087
commit
878ca2058c
@@ -32,7 +32,7 @@ export type RootHost = {
|
||||
end(root: SharedCodexRoot, nativeArchive?: boolean): Promise<void>;
|
||||
};
|
||||
const SettingsSchema = z.object({
|
||||
permissionMode: z.enum(['default', 'read-only', 'safe-yolo', 'yolo']).optional(),
|
||||
permissionMode: z.enum(['default', 'read-only', 'safe-yolo', 'autoReview', 'yolo']).optional(),
|
||||
model: z.string().min(1).optional(), modelReasoningEffort: z.string().nullable().optional(),
|
||||
collaborationMode: z.enum(['default', 'plan']).optional(),
|
||||
serviceTier: z.enum(['fast', 'standard']).nullable().optional(),
|
||||
@@ -264,7 +264,8 @@ export class SharedCodexRoot {
|
||||
const sandbox = record(value.sandboxPolicy ?? value.sandbox).type;
|
||||
this.settings = { ...this.settings, model: value.model,
|
||||
modelReasoningEffort: string(value.effort ?? value.reasoningEffort) ?? null,
|
||||
...(sandbox ? { permissionMode: sandbox === 'dangerFullAccess' ? 'yolo' : sandbox === 'readOnly' ? 'read-only' : 'default' } : {}),
|
||||
...(sandbox ? { permissionMode: sandbox === 'dangerFullAccess' ? 'yolo' : sandbox === 'readOnly' ? 'read-only'
|
||||
: this.settingsNative.approvalsReviewer === 'auto_review' ? 'autoReview' : 'default' } : {}),
|
||||
...('serviceTier' in value ? { serviceTier: value.serviceTier === 'priority' ? 'fast' : 'standard' } : {}),
|
||||
...('collaborationMode' in value ? { collaborationMode: record(value.collaborationMode).mode === 'plan' ? 'plan' as const : 'default' as const } : {})
|
||||
};
|
||||
@@ -405,7 +406,7 @@ export class SharedCodexRoot {
|
||||
}
|
||||
async applySettings(raw: unknown): Promise<{ applied: RuntimeSettings }> {
|
||||
const config = SettingsSchema.parse(raw);
|
||||
if (config.permissionMode === 'safe-yolo') throw new Error('safe-yolo is not a native shared permission mode; choose default, read-only, or yolo');
|
||||
if (config.permissionMode === 'safe-yolo') throw new Error('safe-yolo is not a native shared permission mode; choose default, read-only, autoReview, or yolo');
|
||||
if (Object.keys(config).length === 0) return { applied: this.settings };
|
||||
if (typeof config.modelReasoningEffort === 'string') config.modelReasoningEffort = parseReasoningEffortValue(config.modelReasoningEffort);
|
||||
if (config.modelReasoningEffort === null) {
|
||||
@@ -427,7 +428,8 @@ export class SharedCodexRoot {
|
||||
...(config.personality ? { personality: config.personality } : {}),
|
||||
...(config.modelReasoningEffort !== undefined ? { effort: config.modelReasoningEffort } : {}),
|
||||
...(config.serviceTier !== undefined ? { serviceTier: config.serviceTier === 'fast' ? 'priority' : null } : {}),
|
||||
...(permission ? { approvalPolicy: permission.approvalPolicy, sandboxPolicy: permission.sandboxPolicy } : {}),
|
||||
...(permission ? { approvalPolicy: permission.approvalPolicy, sandboxPolicy: permission.sandboxPolicy,
|
||||
approvalsReviewer: config.permissionMode === 'autoReview' ? 'auto_review' : 'user' } : {}),
|
||||
...(config.collaborationMode ? { collaborationMode: { mode: config.collaborationMode, settings: {
|
||||
model: config.model ?? this.settings.model, reasoning_effort: config.modelReasoningEffort ?? this.settings.modelReasoningEffort,
|
||||
developer_instructions: null
|
||||
@@ -576,7 +578,7 @@ export class SharedCodexRoot {
|
||||
if (command === '/exit') { this.notice('/exit closes a native terminal, not this Web view. Use End session to archive this conversation.'); return null; }
|
||||
if (!command.startsWith('/')) return text;
|
||||
const slash = resolveCodexSlashCommand(text, { commands: await listSlashCommands('codex', this.bootstrap.workingDirectory),
|
||||
permissionMode: this.settings.permissionMode === 'yolo' ? 'yolo' : this.settings.permissionMode === 'read-only' ? 'read-only' : 'default',
|
||||
permissionMode: this.settings.permissionMode === 'yolo' || this.settings.permissionMode === 'read-only' || this.settings.permissionMode === 'autoReview' ? this.settings.permissionMode : 'default',
|
||||
collaborationMode: this.settings.collaborationMode ?? 'default', model: this.settings.model ?? undefined,
|
||||
modelReasoningEffort: parseReasoningEffortValue(this.settings.modelReasoningEffort), serviceTier: this.settings.serviceTier });
|
||||
if (slash.kind === 'passthrough') return text;
|
||||
|
||||
Reference in New Issue
Block a user