mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
app-server: expose thread permission profiles (#18278)
## Why The `PermissionProfile` migration needs app-server clients to see the same constrained permission model that core is using at runtime. Before this PR, thread lifecycle responses only exposed the legacy `SandboxPolicy` shape, so clients still had to infer active permissions from sandbox fields. That makes downstream resume, fork, and override flows harder to make `PermissionProfile`-first. External sandbox policies are intentionally excluded from this canonical view. External enforcement cannot be round-tripped as a `PermissionProfile`, and exposing a lossy root-write profile would let clients accidentally change sandbox semantics if they echo the profile back later. ## What changed - Adds the app-server v2 `PermissionProfile` wire shape, including filesystem permissions and glob scan depth metadata. - Adds `PermissionProfileNetworkPermissions` so the profile response does not expose active network state through the older additional-permissions naming. - Returns `permissionProfile` from thread start, resume, and fork responses when the active sandbox can be represented as a `PermissionProfile`. - Keeps legacy `sandbox` in those responses for compatibility and documents `permissionProfile` as canonical when present. - Makes lifecycle `permissionProfile` nullable and returns `null` for `ExternalSandbox` to avoid exposing a lossy profile. - Regenerates the app-server JSON schema and TypeScript fixtures. ## Verification - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server thread_response_permission_profile_omits_external_sandbox -- --nocapture` - `cargo check --tests -p codex-analytics -p codex-exec -p codex-tui` - `just fix -p codex-app-server-protocol -p codex-app-server -p codex-analytics -p codex-exec -p codex-tui` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/18278). * #18279 * __->__ #18278
This commit is contained in:
@@ -65,6 +65,7 @@ use codex_app_server_protocol::InitializeCapabilities;
|
|||||||
use codex_app_server_protocol::InitializeParams;
|
use codex_app_server_protocol::InitializeParams;
|
||||||
use codex_app_server_protocol::JSONRPCErrorError;
|
use codex_app_server_protocol::JSONRPCErrorError;
|
||||||
use codex_app_server_protocol::NonSteerableTurnKind;
|
use codex_app_server_protocol::NonSteerableTurnKind;
|
||||||
|
use codex_app_server_protocol::PermissionProfile as AppServerPermissionProfile;
|
||||||
use codex_app_server_protocol::RequestId;
|
use codex_app_server_protocol::RequestId;
|
||||||
use codex_app_server_protocol::SandboxPolicy as AppServerSandboxPolicy;
|
use codex_app_server_protocol::SandboxPolicy as AppServerSandboxPolicy;
|
||||||
use codex_app_server_protocol::ServerNotification;
|
use codex_app_server_protocol::ServerNotification;
|
||||||
@@ -91,6 +92,7 @@ use codex_plugin::PluginTelemetryMetadata;
|
|||||||
use codex_protocol::approvals::NetworkApprovalProtocol;
|
use codex_protocol::approvals::NetworkApprovalProtocol;
|
||||||
use codex_protocol::config_types::ApprovalsReviewer;
|
use codex_protocol::config_types::ApprovalsReviewer;
|
||||||
use codex_protocol::config_types::ModeKind;
|
use codex_protocol::config_types::ModeKind;
|
||||||
|
use codex_protocol::models::PermissionProfile as CorePermissionProfile;
|
||||||
use codex_protocol::protocol::AskForApproval;
|
use codex_protocol::protocol::AskForApproval;
|
||||||
use codex_protocol::protocol::HookEventName;
|
use codex_protocol::protocol::HookEventName;
|
||||||
use codex_protocol::protocol::HookRunStatus;
|
use codex_protocol::protocol::HookRunStatus;
|
||||||
@@ -152,11 +154,20 @@ fn sample_thread_start_response(thread_id: &str, ephemeral: bool, model: &str) -
|
|||||||
approval_policy: AppServerAskForApproval::OnFailure,
|
approval_policy: AppServerAskForApproval::OnFailure,
|
||||||
approvals_reviewer: AppServerApprovalsReviewer::User,
|
approvals_reviewer: AppServerApprovalsReviewer::User,
|
||||||
sandbox: AppServerSandboxPolicy::DangerFullAccess,
|
sandbox: AppServerSandboxPolicy::DangerFullAccess,
|
||||||
|
permission_profile: Some(sample_permission_profile()),
|
||||||
reasoning_effort: None,
|
reasoning_effort: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sample_permission_profile() -> AppServerPermissionProfile {
|
||||||
|
CorePermissionProfile::from_legacy_sandbox_policy(
|
||||||
|
&SandboxPolicy::DangerFullAccess,
|
||||||
|
&test_path_buf("/tmp"),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
fn sample_app_server_client_metadata() -> CodexAppServerClientMetadata {
|
fn sample_app_server_client_metadata() -> CodexAppServerClientMetadata {
|
||||||
CodexAppServerClientMetadata {
|
CodexAppServerClientMetadata {
|
||||||
product_client_id: DEFAULT_ORIGINATOR.to_string(),
|
product_client_id: DEFAULT_ORIGINATOR.to_string(),
|
||||||
@@ -203,6 +214,7 @@ fn sample_thread_resume_response_with_source(
|
|||||||
approval_policy: AppServerAskForApproval::OnFailure,
|
approval_policy: AppServerAskForApproval::OnFailure,
|
||||||
approvals_reviewer: AppServerApprovalsReviewer::User,
|
approvals_reviewer: AppServerApprovalsReviewer::User,
|
||||||
sandbox: AppServerSandboxPolicy::DangerFullAccess,
|
sandbox: AppServerSandboxPolicy::DangerFullAccess,
|
||||||
|
permission_profile: Some(sample_permission_profile()),
|
||||||
reasoning_effort: None,
|
reasoning_effort: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-3
@@ -10896,6 +10896,64 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PermissionProfile": {
|
||||||
|
"properties": {
|
||||||
|
"fileSystem": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/PermissionProfileFileSystemPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/PermissionProfileNetworkPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileFileSystemPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"entries": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/v2/FileSystemSandboxEntry"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"globScanMaxDepth": {
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 1.0,
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileNetworkPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Personality": {
|
"Personality": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"none",
|
"none",
|
||||||
@@ -14067,6 +14125,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -14078,7 +14148,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/v2/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
@@ -15457,6 +15532,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -15468,7 +15555,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/v2/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
@@ -15756,6 +15848,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -15767,7 +15871,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/v2/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/v2/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|||||||
+112
-3
@@ -7658,6 +7658,64 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PermissionProfile": {
|
||||||
|
"properties": {
|
||||||
|
"fileSystem": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileFileSystemPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"entries": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"globScanMaxDepth": {
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 1.0,
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileNetworkPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"Personality": {
|
"Personality": {
|
||||||
"enum": [
|
"enum": [
|
||||||
"none",
|
"none",
|
||||||
@@ -11961,6 +12019,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -11972,7 +12042,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
@@ -13351,6 +13426,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -13362,7 +13449,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
@@ -13650,6 +13742,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -13661,7 +13765,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|||||||
+287
-1
@@ -448,6 +448,217 @@
|
|||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"FileSystemAccessMode": {
|
||||||
|
"enum": [
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"none"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"FileSystemPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/AbsolutePathBuf"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"pattern": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"glob_pattern"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"pattern",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"special"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/definitions/FileSystemSpecialPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"FileSystemSandboxEntry": {
|
||||||
|
"properties": {
|
||||||
|
"access": {
|
||||||
|
"$ref": "#/definitions/FileSystemAccessMode"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/FileSystemPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"access",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"FileSystemSpecialPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"root"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "RootFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"minimal"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "MinimalFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"current_working_directory"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"project_roots"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "KindFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"tmpdir"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "TmpdirFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"slash_tmp"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "SlashTmpFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"unknown"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"FileUpdateChange": {
|
"FileUpdateChange": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"diff": {
|
"diff": {
|
||||||
@@ -686,6 +897,64 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PermissionProfile": {
|
||||||
|
"properties": {
|
||||||
|
"fileSystem": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileFileSystemPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"entries": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"globScanMaxDepth": {
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 1.0,
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileNetworkPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"ReadOnlyAccess": {
|
"ReadOnlyAccess": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
@@ -2225,6 +2494,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -2236,7 +2517,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|||||||
@@ -448,6 +448,217 @@
|
|||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"FileSystemAccessMode": {
|
||||||
|
"enum": [
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"none"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"FileSystemPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/AbsolutePathBuf"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"pattern": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"glob_pattern"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"pattern",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"special"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/definitions/FileSystemSpecialPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"FileSystemSandboxEntry": {
|
||||||
|
"properties": {
|
||||||
|
"access": {
|
||||||
|
"$ref": "#/definitions/FileSystemAccessMode"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/FileSystemPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"access",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"FileSystemSpecialPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"root"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "RootFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"minimal"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "MinimalFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"current_working_directory"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"project_roots"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "KindFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"tmpdir"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "TmpdirFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"slash_tmp"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "SlashTmpFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"unknown"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"FileUpdateChange": {
|
"FileUpdateChange": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"diff": {
|
"diff": {
|
||||||
@@ -686,6 +897,64 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PermissionProfile": {
|
||||||
|
"properties": {
|
||||||
|
"fileSystem": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileFileSystemPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"entries": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"globScanMaxDepth": {
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 1.0,
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileNetworkPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"ReadOnlyAccess": {
|
"ReadOnlyAccess": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
@@ -2225,6 +2494,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -2236,7 +2517,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|||||||
@@ -448,6 +448,217 @@
|
|||||||
],
|
],
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"FileSystemAccessMode": {
|
||||||
|
"enum": [
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"none"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"FileSystemPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/AbsolutePathBuf"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"path",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "PathFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"pattern": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"glob_pattern"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"pattern",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "GlobPatternFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"special"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPathType",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"$ref": "#/definitions/FileSystemSpecialPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"value"
|
||||||
|
],
|
||||||
|
"title": "SpecialFileSystemPath",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"FileSystemSandboxEntry": {
|
||||||
|
"properties": {
|
||||||
|
"access": {
|
||||||
|
"$ref": "#/definitions/FileSystemAccessMode"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"$ref": "#/definitions/FileSystemPath"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"access",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"FileSystemSpecialPath": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"root"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "RootFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"minimal"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "MinimalFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"current_working_directory"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "CurrentWorkingDirectoryFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"project_roots"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "KindFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"tmpdir"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "TmpdirFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"slash_tmp"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"title": "SlashTmpFileSystemSpecialPath",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"enum": [
|
||||||
|
"unknown"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"subpath": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind",
|
||||||
|
"path"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"FileUpdateChange": {
|
"FileUpdateChange": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"diff": {
|
"diff": {
|
||||||
@@ -686,6 +897,64 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"PermissionProfile": {
|
||||||
|
"properties": {
|
||||||
|
"fileSystem": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileFileSystemPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"network": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfileNetworkPermissions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileFileSystemPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"entries": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/FileSystemSandboxEntry"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"globScanMaxDepth": {
|
||||||
|
"format": "uint",
|
||||||
|
"minimum": 1.0,
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"entries"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"PermissionProfileNetworkPermissions": {
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"ReadOnlyAccess": {
|
"ReadOnlyAccess": {
|
||||||
"oneOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
@@ -2225,6 +2494,18 @@
|
|||||||
"modelProvider": {
|
"modelProvider": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/PermissionProfile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null,
|
||||||
|
"description": "Canonical active permissions view for this thread when representable. This is `null` for external sandbox policies because external enforcement cannot be round-tripped as a `PermissionProfile`."
|
||||||
|
},
|
||||||
"reasoningEffort": {
|
"reasoningEffort": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -2236,7 +2517,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"$ref": "#/definitions/SandboxPolicy"
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/SandboxPolicy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Legacy sandbox policy retained for compatibility. New clients should use `permissionProfile` when present as the canonical active permissions view."
|
||||||
},
|
},
|
||||||
"serviceTier": {
|
"serviceTier": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||||
|
|
||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { PermissionProfileFileSystemPermissions } from "./PermissionProfileFileSystemPermissions";
|
||||||
|
import type { PermissionProfileNetworkPermissions } from "./PermissionProfileNetworkPermissions";
|
||||||
|
|
||||||
|
export type PermissionProfile = { network: PermissionProfileNetworkPermissions | null, fileSystem: PermissionProfileFileSystemPermissions | null, };
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||||
|
|
||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { FileSystemSandboxEntry } from "./FileSystemSandboxEntry";
|
||||||
|
|
||||||
|
export type PermissionProfileFileSystemPermissions = { entries: Array<FileSystemSandboxEntry>, globScanMaxDepth?: number, };
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||||
|
|
||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
|
export type PermissionProfileNetworkPermissions = { enabled: boolean | null, };
|
||||||
@@ -6,6 +6,7 @@ import type { ReasoningEffort } from "../ReasoningEffort";
|
|||||||
import type { ServiceTier } from "../ServiceTier";
|
import type { ServiceTier } from "../ServiceTier";
|
||||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||||
import type { AskForApproval } from "./AskForApproval";
|
import type { AskForApproval } from "./AskForApproval";
|
||||||
|
import type { PermissionProfile } from "./PermissionProfile";
|
||||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||||
import type { Thread } from "./Thread";
|
import type { Thread } from "./Thread";
|
||||||
|
|
||||||
@@ -17,4 +18,16 @@ instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
|||||||
/**
|
/**
|
||||||
* Reviewer currently used for approval requests on this thread.
|
* Reviewer currently used for approval requests on this thread.
|
||||||
*/
|
*/
|
||||||
approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, };
|
approvalsReviewer: ApprovalsReviewer,
|
||||||
|
/**
|
||||||
|
* Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
* `permissionProfile` when present as the canonical active permissions
|
||||||
|
* view.
|
||||||
|
*/
|
||||||
|
sandbox: SandboxPolicy,
|
||||||
|
/**
|
||||||
|
* Canonical active permissions view for this thread when representable.
|
||||||
|
* This is `null` for external sandbox policies because external
|
||||||
|
* enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
*/
|
||||||
|
permissionProfile: PermissionProfile | null, reasoningEffort: ReasoningEffort | null, };
|
||||||
|
|||||||
+14
-1
@@ -6,6 +6,7 @@ import type { ReasoningEffort } from "../ReasoningEffort";
|
|||||||
import type { ServiceTier } from "../ServiceTier";
|
import type { ServiceTier } from "../ServiceTier";
|
||||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||||
import type { AskForApproval } from "./AskForApproval";
|
import type { AskForApproval } from "./AskForApproval";
|
||||||
|
import type { PermissionProfile } from "./PermissionProfile";
|
||||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||||
import type { Thread } from "./Thread";
|
import type { Thread } from "./Thread";
|
||||||
|
|
||||||
@@ -17,4 +18,16 @@ instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
|||||||
/**
|
/**
|
||||||
* Reviewer currently used for approval requests on this thread.
|
* Reviewer currently used for approval requests on this thread.
|
||||||
*/
|
*/
|
||||||
approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, };
|
approvalsReviewer: ApprovalsReviewer,
|
||||||
|
/**
|
||||||
|
* Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
* `permissionProfile` when present as the canonical active permissions
|
||||||
|
* view.
|
||||||
|
*/
|
||||||
|
sandbox: SandboxPolicy,
|
||||||
|
/**
|
||||||
|
* Canonical active permissions view for this thread when representable.
|
||||||
|
* This is `null` for external sandbox policies because external
|
||||||
|
* enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
*/
|
||||||
|
permissionProfile: PermissionProfile | null, reasoningEffort: ReasoningEffort | null, };
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type { ReasoningEffort } from "../ReasoningEffort";
|
|||||||
import type { ServiceTier } from "../ServiceTier";
|
import type { ServiceTier } from "../ServiceTier";
|
||||||
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
import type { ApprovalsReviewer } from "./ApprovalsReviewer";
|
||||||
import type { AskForApproval } from "./AskForApproval";
|
import type { AskForApproval } from "./AskForApproval";
|
||||||
|
import type { PermissionProfile } from "./PermissionProfile";
|
||||||
import type { SandboxPolicy } from "./SandboxPolicy";
|
import type { SandboxPolicy } from "./SandboxPolicy";
|
||||||
import type { Thread } from "./Thread";
|
import type { Thread } from "./Thread";
|
||||||
|
|
||||||
@@ -17,4 +18,16 @@ instructionSources: Array<AbsolutePathBuf>, approvalPolicy: AskForApproval,
|
|||||||
/**
|
/**
|
||||||
* Reviewer currently used for approval requests on this thread.
|
* Reviewer currently used for approval requests on this thread.
|
||||||
*/
|
*/
|
||||||
approvalsReviewer: ApprovalsReviewer, sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null, };
|
approvalsReviewer: ApprovalsReviewer,
|
||||||
|
/**
|
||||||
|
* Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
* `permissionProfile` when present as the canonical active permissions
|
||||||
|
* view.
|
||||||
|
*/
|
||||||
|
sandbox: SandboxPolicy,
|
||||||
|
/**
|
||||||
|
* Canonical active permissions view for this thread when representable.
|
||||||
|
* This is `null` for external sandbox policies because external
|
||||||
|
* enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
*/
|
||||||
|
permissionProfile: PermissionProfile | null, reasoningEffort: ReasoningEffort | null, };
|
||||||
|
|||||||
@@ -240,6 +240,9 @@ export type { OverriddenMetadata } from "./OverriddenMetadata";
|
|||||||
export type { PatchApplyStatus } from "./PatchApplyStatus";
|
export type { PatchApplyStatus } from "./PatchApplyStatus";
|
||||||
export type { PatchChangeKind } from "./PatchChangeKind";
|
export type { PatchChangeKind } from "./PatchChangeKind";
|
||||||
export type { PermissionGrantScope } from "./PermissionGrantScope";
|
export type { PermissionGrantScope } from "./PermissionGrantScope";
|
||||||
|
export type { PermissionProfile } from "./PermissionProfile";
|
||||||
|
export type { PermissionProfileFileSystemPermissions } from "./PermissionProfileFileSystemPermissions";
|
||||||
|
export type { PermissionProfileNetworkPermissions } from "./PermissionProfileNetworkPermissions";
|
||||||
export type { PermissionsRequestApprovalParams } from "./PermissionsRequestApprovalParams";
|
export type { PermissionsRequestApprovalParams } from "./PermissionsRequestApprovalParams";
|
||||||
export type { PermissionsRequestApprovalResponse } from "./PermissionsRequestApprovalResponse";
|
export type { PermissionsRequestApprovalResponse } from "./PermissionsRequestApprovalResponse";
|
||||||
export type { PlanDeltaNotification } from "./PlanDeltaNotification";
|
export type { PlanDeltaNotification } from "./PlanDeltaNotification";
|
||||||
|
|||||||
@@ -1435,6 +1435,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_client_response() -> Result<()> {
|
fn serialize_client_response() -> Result<()> {
|
||||||
|
let cwd = absolute_path("/tmp");
|
||||||
let response = ClientResponse::ThreadStart {
|
let response = ClientResponse::ThreadStart {
|
||||||
request_id: RequestId::Integer(7),
|
request_id: RequestId::Integer(7),
|
||||||
response: v2::ThreadStartResponse {
|
response: v2::ThreadStartResponse {
|
||||||
@@ -1448,7 +1449,7 @@ mod tests {
|
|||||||
updated_at: 2,
|
updated_at: 2,
|
||||||
status: v2::ThreadStatus::Idle,
|
status: v2::ThreadStatus::Idle,
|
||||||
path: None,
|
path: None,
|
||||||
cwd: absolute_path("/tmp"),
|
cwd: cwd.clone(),
|
||||||
cli_version: "0.0.0".to_string(),
|
cli_version: "0.0.0".to_string(),
|
||||||
source: v2::SessionSource::Exec,
|
source: v2::SessionSource::Exec,
|
||||||
agent_nickname: None,
|
agent_nickname: None,
|
||||||
@@ -1460,11 +1461,18 @@ mod tests {
|
|||||||
model: "gpt-5".to_string(),
|
model: "gpt-5".to_string(),
|
||||||
model_provider: "openai".to_string(),
|
model_provider: "openai".to_string(),
|
||||||
service_tier: None,
|
service_tier: None,
|
||||||
cwd: absolute_path("/tmp"),
|
cwd: cwd.clone(),
|
||||||
instruction_sources: vec![absolute_path("/tmp/AGENTS.md")],
|
instruction_sources: vec![absolute_path("/tmp/AGENTS.md")],
|
||||||
approval_policy: v2::AskForApproval::OnFailure,
|
approval_policy: v2::AskForApproval::OnFailure,
|
||||||
approvals_reviewer: v2::ApprovalsReviewer::User,
|
approvals_reviewer: v2::ApprovalsReviewer::User,
|
||||||
sandbox: v2::SandboxPolicy::DangerFullAccess,
|
sandbox: v2::SandboxPolicy::DangerFullAccess,
|
||||||
|
permission_profile: Some(
|
||||||
|
codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||||
|
&codex_protocol::protocol::SandboxPolicy::DangerFullAccess,
|
||||||
|
cwd.as_path(),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
reasoning_effort: None,
|
reasoning_effort: None,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -1507,6 +1515,24 @@ mod tests {
|
|||||||
"sandbox": {
|
"sandbox": {
|
||||||
"type": "dangerFullAccess"
|
"type": "dangerFullAccess"
|
||||||
},
|
},
|
||||||
|
"permissionProfile": {
|
||||||
|
"network": {
|
||||||
|
"enabled": true,
|
||||||
|
},
|
||||||
|
"fileSystem": {
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"path": {
|
||||||
|
"type": "special",
|
||||||
|
"value": {
|
||||||
|
"kind": "root",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"access": "write",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
"reasoningEffort": null
|
"reasoningEffort": null
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1225,6 +1225,13 @@ pub struct AdditionalNetworkPermissions {
|
|||||||
pub enabled: Option<bool>,
|
pub enabled: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub struct PermissionProfileNetworkPermissions {
|
||||||
|
pub enabled: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<CoreNetworkPermissions> for AdditionalNetworkPermissions {
|
impl From<CoreNetworkPermissions> for AdditionalNetworkPermissions {
|
||||||
fn from(value: CoreNetworkPermissions) -> Self {
|
fn from(value: CoreNetworkPermissions) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -1241,6 +1248,22 @@ impl From<AdditionalNetworkPermissions> for CoreNetworkPermissions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<CoreNetworkPermissions> for PermissionProfileNetworkPermissions {
|
||||||
|
fn from(value: CoreNetworkPermissions) -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: value.enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PermissionProfileNetworkPermissions> for CoreNetworkPermissions {
|
||||||
|
fn from(value: PermissionProfileNetworkPermissions) -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: value.enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
@@ -1383,6 +1406,70 @@ impl From<FileSystemSandboxEntry> for CoreFileSystemSandboxEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub struct PermissionProfileFileSystemPermissions {
|
||||||
|
pub entries: Vec<FileSystemSandboxEntry>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
#[ts(optional)]
|
||||||
|
pub glob_scan_max_depth: Option<NonZeroUsize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreFileSystemPermissions> for PermissionProfileFileSystemPermissions {
|
||||||
|
fn from(value: CoreFileSystemPermissions) -> Self {
|
||||||
|
Self {
|
||||||
|
entries: value
|
||||||
|
.entries
|
||||||
|
.into_iter()
|
||||||
|
.map(FileSystemSandboxEntry::from)
|
||||||
|
.collect(),
|
||||||
|
glob_scan_max_depth: value.glob_scan_max_depth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PermissionProfileFileSystemPermissions> for CoreFileSystemPermissions {
|
||||||
|
fn from(value: PermissionProfileFileSystemPermissions) -> Self {
|
||||||
|
Self {
|
||||||
|
entries: value
|
||||||
|
.entries
|
||||||
|
.into_iter()
|
||||||
|
.map(CoreFileSystemSandboxEntry::from)
|
||||||
|
.collect(),
|
||||||
|
glob_scan_max_depth: value.glob_scan_max_depth,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub struct PermissionProfile {
|
||||||
|
pub network: Option<PermissionProfileNetworkPermissions>,
|
||||||
|
pub file_system: Option<PermissionProfileFileSystemPermissions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CorePermissionProfile> for PermissionProfile {
|
||||||
|
fn from(value: CorePermissionProfile) -> Self {
|
||||||
|
Self {
|
||||||
|
network: value.network.map(PermissionProfileNetworkPermissions::from),
|
||||||
|
file_system: value
|
||||||
|
.file_system
|
||||||
|
.map(PermissionProfileFileSystemPermissions::from),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PermissionProfile> for CorePermissionProfile {
|
||||||
|
fn from(value: PermissionProfile) -> Self {
|
||||||
|
Self {
|
||||||
|
network: value.network.map(CoreNetworkPermissions::from),
|
||||||
|
file_system: value.file_system.map(CoreFileSystemPermissions::from),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(export_to = "v2/")]
|
#[ts(export_to = "v2/")]
|
||||||
@@ -3127,7 +3214,15 @@ pub struct ThreadStartResponse {
|
|||||||
pub approval_policy: AskForApproval,
|
pub approval_policy: AskForApproval,
|
||||||
/// Reviewer currently used for approval requests on this thread.
|
/// Reviewer currently used for approval requests on this thread.
|
||||||
pub approvals_reviewer: ApprovalsReviewer,
|
pub approvals_reviewer: ApprovalsReviewer,
|
||||||
|
/// Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
/// `permissionProfile` when present as the canonical active permissions
|
||||||
|
/// view.
|
||||||
pub sandbox: SandboxPolicy,
|
pub sandbox: SandboxPolicy,
|
||||||
|
/// Canonical active permissions view for this thread when representable.
|
||||||
|
/// This is `null` for external sandbox policies because external
|
||||||
|
/// enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
#[serde(default)]
|
||||||
|
pub permission_profile: Option<PermissionProfile>,
|
||||||
pub reasoning_effort: Option<ReasoningEffort>,
|
pub reasoning_effort: Option<ReasoningEffort>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3216,7 +3311,15 @@ pub struct ThreadResumeResponse {
|
|||||||
pub approval_policy: AskForApproval,
|
pub approval_policy: AskForApproval,
|
||||||
/// Reviewer currently used for approval requests on this thread.
|
/// Reviewer currently used for approval requests on this thread.
|
||||||
pub approvals_reviewer: ApprovalsReviewer,
|
pub approvals_reviewer: ApprovalsReviewer,
|
||||||
|
/// Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
/// `permissionProfile` when present as the canonical active permissions
|
||||||
|
/// view.
|
||||||
pub sandbox: SandboxPolicy,
|
pub sandbox: SandboxPolicy,
|
||||||
|
/// Canonical active permissions view for this thread when representable.
|
||||||
|
/// This is `null` for external sandbox policies because external
|
||||||
|
/// enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
#[serde(default)]
|
||||||
|
pub permission_profile: Option<PermissionProfile>,
|
||||||
pub reasoning_effort: Option<ReasoningEffort>,
|
pub reasoning_effort: Option<ReasoningEffort>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3296,7 +3399,15 @@ pub struct ThreadForkResponse {
|
|||||||
pub approval_policy: AskForApproval,
|
pub approval_policy: AskForApproval,
|
||||||
/// Reviewer currently used for approval requests on this thread.
|
/// Reviewer currently used for approval requests on this thread.
|
||||||
pub approvals_reviewer: ApprovalsReviewer,
|
pub approvals_reviewer: ApprovalsReviewer,
|
||||||
|
/// Legacy sandbox policy retained for compatibility. New clients should use
|
||||||
|
/// `permissionProfile` when present as the canonical active permissions
|
||||||
|
/// view.
|
||||||
pub sandbox: SandboxPolicy,
|
pub sandbox: SandboxPolicy,
|
||||||
|
/// Canonical active permissions view for this thread when representable.
|
||||||
|
/// This is `null` for external sandbox policies because external
|
||||||
|
/// enforcement cannot be round-tripped as a `PermissionProfile`.
|
||||||
|
#[serde(default)]
|
||||||
|
pub permission_profile: Option<PermissionProfile>,
|
||||||
pub reasoning_effort: Option<ReasoningEffort>,
|
pub reasoning_effort: Option<ReasoningEffort>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7419,6 +7530,47 @@ mod tests {
|
|||||||
.expect_err("zero glob scan depth should fail deserialization");
|
.expect_err("zero glob scan depth should fail deserialization");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn permission_profile_file_system_permissions_preserves_glob_scan_depth() {
|
||||||
|
let core_permissions = CoreFileSystemPermissions {
|
||||||
|
entries: vec![CoreFileSystemSandboxEntry {
|
||||||
|
path: CoreFileSystemPath::GlobPattern {
|
||||||
|
pattern: "**/*.env".to_string(),
|
||||||
|
},
|
||||||
|
access: CoreFileSystemAccessMode::None,
|
||||||
|
}],
|
||||||
|
glob_scan_max_depth: NonZeroUsize::new(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
let permissions = PermissionProfileFileSystemPermissions::from(core_permissions.clone());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
permissions,
|
||||||
|
PermissionProfileFileSystemPermissions {
|
||||||
|
entries: vec![FileSystemSandboxEntry {
|
||||||
|
path: FileSystemPath::GlobPattern {
|
||||||
|
pattern: "**/*.env".to_string(),
|
||||||
|
},
|
||||||
|
access: FileSystemAccessMode::None,
|
||||||
|
}],
|
||||||
|
glob_scan_max_depth: NonZeroUsize::new(2),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
CoreFileSystemPermissions::from(permissions),
|
||||||
|
core_permissions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn permission_profile_file_system_permissions_rejects_zero_glob_scan_depth() {
|
||||||
|
serde_json::from_value::<PermissionProfileFileSystemPermissions>(json!({
|
||||||
|
"entries": [],
|
||||||
|
"globScanMaxDepth": 0,
|
||||||
|
}))
|
||||||
|
.expect_err("zero glob scan depth should fail deserialization");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn permissions_request_approval_response_uses_granted_permission_profile_without_macos() {
|
fn permissions_request_approval_response_uses_granted_permission_profile_without_macos() {
|
||||||
let read_only_path = if cfg!(windows) {
|
let read_only_path = if cfg!(windows) {
|
||||||
@@ -9708,7 +9860,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn thread_lifecycle_responses_default_missing_instruction_sources() {
|
fn thread_lifecycle_responses_default_missing_compat_fields() {
|
||||||
let response = json!({
|
let response = json!({
|
||||||
"thread": {
|
"thread": {
|
||||||
"id": "thread-id",
|
"id": "thread-id",
|
||||||
@@ -9749,6 +9901,9 @@ mod tests {
|
|||||||
assert_eq!(start.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
assert_eq!(start.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||||
assert_eq!(resume.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
assert_eq!(resume.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||||
assert_eq!(fork.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
assert_eq!(fork.instruction_sources, Vec::<AbsolutePathBuf>::new());
|
||||||
|
assert_eq!(start.permission_profile, None);
|
||||||
|
assert_eq!(resume.permission_profile, None);
|
||||||
|
assert_eq!(fork.permission_profile, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -2691,6 +2691,11 @@ impl CodexMessageProcessor {
|
|||||||
/*has_in_progress_turn*/ false,
|
/*has_in_progress_turn*/ false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let permission_profile = thread_response_permission_profile(
|
||||||
|
&config_snapshot.sandbox_policy,
|
||||||
|
config_snapshot.permission_profile,
|
||||||
|
);
|
||||||
|
|
||||||
let response = ThreadStartResponse {
|
let response = ThreadStartResponse {
|
||||||
thread: thread.clone(),
|
thread: thread.clone(),
|
||||||
model: config_snapshot.model,
|
model: config_snapshot.model,
|
||||||
@@ -2701,6 +2706,7 @@ impl CodexMessageProcessor {
|
|||||||
approval_policy: config_snapshot.approval_policy.into(),
|
approval_policy: config_snapshot.approval_policy.into(),
|
||||||
approvals_reviewer: config_snapshot.approvals_reviewer.into(),
|
approvals_reviewer: config_snapshot.approvals_reviewer.into(),
|
||||||
sandbox: config_snapshot.sandbox_policy.into(),
|
sandbox: config_snapshot.sandbox_policy.into(),
|
||||||
|
permission_profile,
|
||||||
reasoning_effort: config_snapshot.reasoning_effort,
|
reasoning_effort: config_snapshot.reasoning_effort,
|
||||||
};
|
};
|
||||||
if listener_task_context.general_analytics_enabled {
|
if listener_task_context.general_analytics_enabled {
|
||||||
@@ -4423,6 +4429,10 @@ impl CodexMessageProcessor {
|
|||||||
thread_status,
|
thread_status,
|
||||||
/*has_live_in_progress_turn*/ false,
|
/*has_live_in_progress_turn*/ false,
|
||||||
);
|
);
|
||||||
|
let permission_profile = thread_response_permission_profile(
|
||||||
|
&session_configured.sandbox_policy,
|
||||||
|
codex_thread.config_snapshot().await.permission_profile,
|
||||||
|
);
|
||||||
|
|
||||||
let response = ThreadResumeResponse {
|
let response = ThreadResumeResponse {
|
||||||
thread,
|
thread,
|
||||||
@@ -4434,6 +4444,7 @@ impl CodexMessageProcessor {
|
|||||||
approval_policy: session_configured.approval_policy.into(),
|
approval_policy: session_configured.approval_policy.into(),
|
||||||
approvals_reviewer: session_configured.approvals_reviewer.into(),
|
approvals_reviewer: session_configured.approvals_reviewer.into(),
|
||||||
sandbox: session_configured.sandbox_policy.into(),
|
sandbox: session_configured.sandbox_policy.into(),
|
||||||
|
permission_profile,
|
||||||
reasoning_effort: session_configured.reasoning_effort,
|
reasoning_effort: session_configured.reasoning_effort,
|
||||||
};
|
};
|
||||||
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
||||||
@@ -5068,6 +5079,10 @@ impl CodexMessageProcessor {
|
|||||||
.await,
|
.await,
|
||||||
/*has_in_progress_turn*/ false,
|
/*has_in_progress_turn*/ false,
|
||||||
);
|
);
|
||||||
|
let permission_profile = thread_response_permission_profile(
|
||||||
|
&session_configured.sandbox_policy,
|
||||||
|
forked_thread.config_snapshot().await.permission_profile,
|
||||||
|
);
|
||||||
|
|
||||||
let response = ThreadForkResponse {
|
let response = ThreadForkResponse {
|
||||||
thread: thread.clone(),
|
thread: thread.clone(),
|
||||||
@@ -5079,6 +5094,7 @@ impl CodexMessageProcessor {
|
|||||||
approval_policy: session_configured.approval_policy.into(),
|
approval_policy: session_configured.approval_policy.into(),
|
||||||
approvals_reviewer: session_configured.approvals_reviewer.into(),
|
approvals_reviewer: session_configured.approvals_reviewer.into(),
|
||||||
sandbox: session_configured.sandbox_policy.into(),
|
sandbox: session_configured.sandbox_policy.into(),
|
||||||
|
permission_profile,
|
||||||
reasoning_effort: session_configured.reasoning_effort,
|
reasoning_effort: session_configured.reasoning_effort,
|
||||||
};
|
};
|
||||||
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
if self.config.features.enabled(Feature::GeneralAnalytics) {
|
||||||
@@ -8456,11 +8472,15 @@ async fn handle_pending_thread_resume_request(
|
|||||||
approval_policy,
|
approval_policy,
|
||||||
approvals_reviewer,
|
approvals_reviewer,
|
||||||
sandbox_policy,
|
sandbox_policy,
|
||||||
|
permission_profile,
|
||||||
cwd,
|
cwd,
|
||||||
reasoning_effort,
|
reasoning_effort,
|
||||||
..
|
..
|
||||||
} = pending.config_snapshot;
|
} = pending.config_snapshot;
|
||||||
let instruction_sources = pending.instruction_sources;
|
let instruction_sources = pending.instruction_sources;
|
||||||
|
let permission_profile =
|
||||||
|
thread_response_permission_profile(&sandbox_policy, permission_profile);
|
||||||
|
|
||||||
let response = ThreadResumeResponse {
|
let response = ThreadResumeResponse {
|
||||||
thread,
|
thread,
|
||||||
model,
|
model,
|
||||||
@@ -8471,6 +8491,7 @@ async fn handle_pending_thread_resume_request(
|
|||||||
approval_policy: approval_policy.into(),
|
approval_policy: approval_policy.into(),
|
||||||
approvals_reviewer: approvals_reviewer.into(),
|
approvals_reviewer: approvals_reviewer.into(),
|
||||||
sandbox: sandbox_policy.into(),
|
sandbox: sandbox_policy.into(),
|
||||||
|
permission_profile,
|
||||||
reasoning_effort,
|
reasoning_effort,
|
||||||
};
|
};
|
||||||
let token_usage_thread = response.thread.clone();
|
let token_usage_thread = response.thread.clone();
|
||||||
@@ -9573,6 +9594,20 @@ fn with_thread_spawn_agent_metadata(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn thread_response_permission_profile(
|
||||||
|
sandbox_policy: &codex_protocol::protocol::SandboxPolicy,
|
||||||
|
permission_profile: codex_protocol::models::PermissionProfile,
|
||||||
|
) -> Option<codex_app_server_protocol::PermissionProfile> {
|
||||||
|
match sandbox_policy {
|
||||||
|
codex_protocol::protocol::SandboxPolicy::DangerFullAccess
|
||||||
|
| codex_protocol::protocol::SandboxPolicy::ReadOnly { .. }
|
||||||
|
| codex_protocol::protocol::SandboxPolicy::WorkspaceWrite { .. } => {
|
||||||
|
Some(permission_profile.into())
|
||||||
|
}
|
||||||
|
codex_protocol::protocol::SandboxPolicy::ExternalSandbox { .. } => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_datetime(timestamp: Option<&str>) -> Option<DateTime<Utc>> {
|
fn parse_datetime(timestamp: Option<&str>) -> Option<DateTime<Utc>> {
|
||||||
timestamp.and_then(|ts| {
|
timestamp.and_then(|ts| {
|
||||||
chrono::DateTime::parse_from_rfc3339(ts)
|
chrono::DateTime::parse_from_rfc3339(ts)
|
||||||
@@ -10061,6 +10096,29 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn thread_response_permission_profile_omits_external_sandbox() {
|
||||||
|
let cwd = test_path_buf("/tmp").abs();
|
||||||
|
let profile = codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||||
|
&SandboxPolicy::DangerFullAccess,
|
||||||
|
cwd.as_path(),
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
thread_response_permission_profile(
|
||||||
|
&SandboxPolicy::ExternalSandbox {
|
||||||
|
network_access: codex_protocol::protocol::NetworkAccess::Restricted,
|
||||||
|
},
|
||||||
|
profile.clone(),
|
||||||
|
),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
thread_response_permission_profile(&SandboxPolicy::DangerFullAccess, profile.clone()),
|
||||||
|
Some(profile.into())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn config_load_error_marks_cloud_requirements_failures_for_relogin() {
|
fn config_load_error_marks_cloud_requirements_failures_for_relogin() {
|
||||||
let err = std::io::Error::other(CloudRequirementsLoadError::new(
|
let err = std::io::Error::other(CloudRequirementsLoadError::new(
|
||||||
|
|||||||
@@ -422,6 +422,13 @@ fn session_configured_from_thread_response_uses_review_policy_from_response() {
|
|||||||
exclude_tmpdir_env_var: false,
|
exclude_tmpdir_env_var: false,
|
||||||
exclude_slash_tmp: false,
|
exclude_slash_tmp: false,
|
||||||
},
|
},
|
||||||
|
permission_profile: Some(
|
||||||
|
codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||||
|
&codex_protocol::protocol::SandboxPolicy::new_workspace_write_policy(),
|
||||||
|
&test_path_buf("/tmp"),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
reasoning_effort: None,
|
reasoning_effort: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1504,6 +1504,13 @@ mod tests {
|
|||||||
approval_policy: codex_protocol::protocol::AskForApproval::Never.into(),
|
approval_policy: codex_protocol::protocol::AskForApproval::Never.into(),
|
||||||
approvals_reviewer: codex_app_server_protocol::ApprovalsReviewer::User,
|
approvals_reviewer: codex_app_server_protocol::ApprovalsReviewer::User,
|
||||||
sandbox: codex_protocol::protocol::SandboxPolicy::new_read_only_policy().into(),
|
sandbox: codex_protocol::protocol::SandboxPolicy::new_read_only_policy().into(),
|
||||||
|
permission_profile: Some(
|
||||||
|
codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||||
|
&codex_protocol::protocol::SandboxPolicy::new_read_only_policy(),
|
||||||
|
&test_path_buf("/tmp/project"),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
reasoning_effort: None,
|
reasoning_effort: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user