mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
fix(runnerd): negotiate Codex permission profile encoding
This commit is contained in:
1 parent
3dbce8a986
commit
999ce0faef
2 files changed
+49
-12
No files matched your search
@@ -84,6 +84,19 @@ fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}) {
|
||||
return Err("authorized tool was not registered".into());
|
||||
}
|
||||
if request
|
||||
.pointer("/params/permissions")
|
||||
.is_some_and(Value::is_string)
|
||||
{
|
||||
send(json!({
|
||||
"id": id,
|
||||
"error": {
|
||||
"code": -32600,
|
||||
"message": "Invalid request: invalid type: string, expected internally tagged enum PermissionProfileSelectionParams"
|
||||
}
|
||||
}))?;
|
||||
continue;
|
||||
}
|
||||
let config = request.pointer("/params/config").and_then(Value::as_object);
|
||||
planning_thread = request
|
||||
.pointer("/params/permissions/id")
|
||||
|
||||
@@ -600,6 +600,7 @@ pub struct CodexProvider {
|
||||
pending_runtime_requests: BTreeMap<String, PendingCodexRuntimeRequest>,
|
||||
collaboration_mode: String,
|
||||
collaboration_mode_payload: Option<Value>,
|
||||
structured_permission_profile: bool,
|
||||
trace: Option<ProviderTraceSink>,
|
||||
last_trace_frame_id: Option<u64>,
|
||||
}
|
||||
@@ -612,6 +613,19 @@ struct PendingCodexRuntimeRequest {
|
||||
question_set: Value,
|
||||
}
|
||||
|
||||
fn permission_profile_params(profile_id: &str, structured: bool) -> Value {
|
||||
if structured {
|
||||
json!({"type": "profile", "id": profile_id})
|
||||
} else {
|
||||
json!(profile_id)
|
||||
}
|
||||
}
|
||||
|
||||
fn requires_structured_permission_profile(error: &LocalRunnerError) -> bool {
|
||||
let detail = error.to_string();
|
||||
detail.contains("invalid type: string") && detail.contains("PermissionProfileSelectionParams")
|
||||
}
|
||||
|
||||
fn latest_active_provider_turn_id(thread_read: &Value) -> Option<String> {
|
||||
thread_read
|
||||
.pointer("/thread/turns")
|
||||
@@ -1180,6 +1194,7 @@ impl CodexProvider {
|
||||
pending_runtime_requests: BTreeMap::new(),
|
||||
collaboration_mode: config.collaboration_mode.clone(),
|
||||
collaboration_mode_payload: None,
|
||||
structured_permission_profile: false,
|
||||
trace: ProviderTraceSink::from_environment(config.kind),
|
||||
last_trace_frame_id: None,
|
||||
};
|
||||
@@ -1203,19 +1218,19 @@ impl CodexProvider {
|
||||
));
|
||||
}
|
||||
let permission_profile = if config.collaboration_mode == "plan" {
|
||||
json!({"type": "profile", "id": "paperclip-runner-workspace-read-only"})
|
||||
"paperclip-runner-workspace-read-only"
|
||||
} else {
|
||||
json!({"type": "profile", "id": "paperclip-runner-workspace-only"})
|
||||
"paperclip-runner-workspace-only"
|
||||
};
|
||||
let opened = if let Some(thread_id) = resume_thread_id {
|
||||
provider.request(
|
||||
let (open_method, mut open_params) = if let Some(thread_id) = resume_thread_id {
|
||||
(
|
||||
"thread/resume",
|
||||
json!({
|
||||
"threadId": thread_id,
|
||||
"cwd": config.cwd,
|
||||
"model": config.model,
|
||||
"approvalPolicy": config.approval_policy,
|
||||
"permissions": permission_profile,
|
||||
"permissions": permission_profile_params(permission_profile, false),
|
||||
"runtimeWorkspaceRoots": [config.cwd],
|
||||
"config": isolated_thread_config(
|
||||
config.include_collaboration_mode_instructions,
|
||||
@@ -1226,15 +1241,15 @@ impl CodexProvider {
|
||||
"experimentalRawEvents": true,
|
||||
"persistExtendedHistory": true,
|
||||
}),
|
||||
)?
|
||||
)
|
||||
} else {
|
||||
provider.request(
|
||||
(
|
||||
"thread/start",
|
||||
json!({
|
||||
"cwd": config.cwd,
|
||||
"model": config.model,
|
||||
"approvalPolicy": config.approval_policy,
|
||||
"permissions": permission_profile,
|
||||
"permissions": permission_profile_params(permission_profile, false),
|
||||
"runtimeWorkspaceRoots": [config.cwd],
|
||||
"config": isolated_thread_config(
|
||||
config.include_collaboration_mode_instructions,
|
||||
@@ -1245,7 +1260,16 @@ impl CodexProvider {
|
||||
"experimentalRawEvents": true,
|
||||
"persistExtendedHistory": true,
|
||||
}),
|
||||
)?
|
||||
)
|
||||
};
|
||||
let opened = match provider.request(open_method, open_params.clone()) {
|
||||
Ok(opened) => opened,
|
||||
Err(error) if requires_structured_permission_profile(&error) => {
|
||||
open_params["permissions"] = permission_profile_params(permission_profile, true);
|
||||
provider.structured_permission_profile = true;
|
||||
provider.request(open_method, open_params)?
|
||||
}
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
if config.collaboration_mode == "plan" {
|
||||
let presets = provider
|
||||
@@ -1318,14 +1342,14 @@ impl CodexProvider {
|
||||
pub fn start_turn(&mut self, message: &str, cwd: &str) -> Result<Value, LocalRunnerError> {
|
||||
let thread_id = self.thread_id.clone();
|
||||
let permission_profile = if self.collaboration_mode == "plan" {
|
||||
json!({"type": "profile", "id": "paperclip-runner-workspace-read-only"})
|
||||
"paperclip-runner-workspace-read-only"
|
||||
} else {
|
||||
json!({"type": "profile", "id": "paperclip-runner-workspace-only"})
|
||||
"paperclip-runner-workspace-only"
|
||||
};
|
||||
let mut params = json!({
|
||||
"threadId": thread_id,
|
||||
"cwd": cwd,
|
||||
"permissions": permission_profile,
|
||||
"permissions": permission_profile_params(permission_profile, self.structured_permission_profile),
|
||||
"runtimeWorkspaceRoots": [cwd],
|
||||
"input": [{"type": "text", "text": message, "text_elements": []}],
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user