Add sidebar run permission preset for scheduled jobs.

Default inherits Host new-session access mode; humans can raise to workspace-write or full access. Agents never see or set the field.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-10 22:08:39 +08:00
parent ad6e90f197
commit 8cf624ce7f
8 changed files with 140 additions and 4 deletions

View file

@ -97,6 +97,38 @@ export function agentMayMutateJob(job) {
return normalizeAgentAccess(job) === 'allow'
}
/** Host permission-preset ids (DSH 访问模式). Empty = inherit Host default for new sessions. */
export const PERMISSION_PRESET_IDS = Object.freeze([
'read-only',
'workspace-write',
'danger-full-access',
])
/**
* @param {unknown} input job or raw value
* @returns {''|'read-only'|'workspace-write'|'danger-full-access'}
*/
export function normalizePermissionPreset(input) {
const raw = input && typeof input === 'object' && !Array.isArray(input)
? (input.permissionPreset ?? input.permission_preset ?? input.accessMode ?? input.access_mode)
: input
const value = String(raw || '').trim().toLowerCase()
if (!value || value === 'default' || value === 'inherit' || value === 'host') return ''
if (value === 'readonly' || value === 'read_only' || value === 'view' || value === 'read-only') {
return 'read-only'
}
if (value === 'workspace' || value === 'workspace_write' || value === 'write' || value === 'workspace-write') {
return 'workspace-write'
}
if (value === 'full' || value === 'fullaccess' || value === 'full_access' || value === 'danger-full-access') {
return 'danger-full-access'
}
if (PERMISSION_PRESET_IDS.includes(value)) return value
const error = new Error(`permissionPreset must be empty|read-only|workspace-write|danger-full-access (got ${JSON.stringify(raw)})`)
error.code = 'INVALID_PERMISSION_PRESET'
throw error
}
/**
* Repair provider/model pairs when LLMs or hosts pass a combined "provider/model"
* route in one or both fields (e.g. provider=model="zte/Qwen3-…" → zte + Qwen3-…).
@ -190,6 +222,7 @@ export function createJobRecord(input, state, now) {
settings.historyLimit,
)
const agentAccess = normalizeAgentAccess(input)
const permissionPreset = normalizePermissionPreset(input)
const job = {
id: String(input.id || newId()),
name,
@ -204,6 +237,7 @@ export function createJobRecord(input, state, now) {
reasoningEffort: model.reasoningEffort,
agentPreset,
agentAccess,
permissionPreset,
delivery,
mirrorToSession,
ownerEmpNo,