mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Clarify model-generated and legacy app path types (#28577)
## Why `ApiPathString` kind of implies that it can be used anywhere we pull a path out of JSON, but it's not really appropriate for tool arguments when the model might generate relative paths. Prefer `String` for model-generated paths and we can handle the conversion per feature for now and define a shared abstraction later if it makes sense. # What Rename `ApiPathString` to `AppLegacyPathString` to clarify its role. Expand the `path-types` skill to tell the model to leave tool args as bare strings.
This commit is contained in:
committed by
GitHub
Unverified
parent
a50671e748
commit
322b83de5e
@@ -9,10 +9,12 @@ Apply this guidance when defining new types. Change existing code only when expl
|
||||
and keep edits minimal and proportional. Treat these rules as the target state of an ongoing
|
||||
migration; if compliance is difficult, ask the user how to proceed.
|
||||
|
||||
- In app-server protocol types, use `ApiPathString` for backwards compatibility during the URI
|
||||
- In app-server protocol types, use `LegacyAppPathString` for backwards compatibility during the URI
|
||||
migration. At the protocol boundary, convert it to `PathUri` and use `PathUri` internally. For
|
||||
host-local logic, such as some config values, use `AbsolutePathBuf` or `PathBuf` instead.
|
||||
- In exec-server protocol types, use `PathUri`. Internally, use `PathUri` or `AbsolutePathBuf` as
|
||||
appropriate.
|
||||
- In dependencies shared by both servers, use `PathUri` or separate APIs that decouple their use
|
||||
cases.
|
||||
- Tool call arguments that the model is expected to generate should be deserialized as regular
|
||||
`String`s with feature-specific path handling code.
|
||||
|
||||
+6
-6
@@ -27,7 +27,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -37,7 +37,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -84,9 +84,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"CommandAction": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -289,7 +286,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -472,6 +469,9 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkApprovalContext": {
|
||||
"properties": {
|
||||
"host": {
|
||||
|
||||
+6
-6
@@ -27,7 +27,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -37,7 +37,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -58,9 +58,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"FileSystemAccessMode": {
|
||||
"enum": [
|
||||
"read",
|
||||
@@ -74,7 +71,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -257,6 +254,9 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"RequestPermissionProfile": {
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
||||
+6
-6
@@ -23,7 +23,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -33,7 +33,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -54,9 +54,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"FileSystemAccessMode": {
|
||||
"enum": [
|
||||
"read",
|
||||
@@ -70,7 +67,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -278,6 +275,9 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"PermissionGrantScope": {
|
||||
"enum": [
|
||||
"turn",
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -117,7 +117,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -164,9 +164,6 @@
|
||||
"AgentPath": {
|
||||
"type": "string"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"AppBranding": {
|
||||
"description": "EXPERIMENTAL - app metadata returned by app-list APIs.",
|
||||
"properties": {
|
||||
@@ -1345,7 +1342,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -2339,6 +2336,9 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"McpServerOauthLoginCompletedNotification": {
|
||||
"properties": {
|
||||
"error": {
|
||||
|
||||
+6
-6
@@ -27,7 +27,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -37,7 +37,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -84,9 +84,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"ApplyPatchApprovalParams": {
|
||||
"properties": {
|
||||
"callId": {
|
||||
@@ -643,7 +640,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -826,6 +823,9 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"McpElicitationArrayType": {
|
||||
"enum": [
|
||||
"array"
|
||||
|
||||
+6
-6
@@ -6071,7 +6071,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/ApiPathString"
|
||||
"$ref": "#/definitions/v2/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -6081,7 +6081,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/ApiPathString"
|
||||
"$ref": "#/definitions/v2/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -6193,9 +6193,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"AppBranding": {
|
||||
"description": "EXPERIMENTAL - app metadata returned by app-list APIs.",
|
||||
"properties": {
|
||||
@@ -9505,7 +9502,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/v2/ApiPathString"
|
||||
"$ref": "#/definitions/v2/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -11184,6 +11181,9 @@
|
||||
"title": "ItemStartedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"ListMcpServerStatusParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
+6
-6
@@ -273,7 +273,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -283,7 +283,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -395,9 +395,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"AppBranding": {
|
||||
"description": "EXPERIMENTAL - app metadata returned by app-list APIs.",
|
||||
"properties": {
|
||||
@@ -5798,7 +5795,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -7637,6 +7634,9 @@
|
||||
"title": "ItemStartedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"ListMcpServerStatusParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
Generated
+6
-6
@@ -27,7 +27,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -37,7 +37,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -58,9 +58,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"AutoReviewDecisionSource": {
|
||||
"description": "[UNSTABLE] Source that produced a terminal approval auto-review decision.",
|
||||
"enum": [
|
||||
@@ -81,7 +78,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -536,6 +533,9 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkApprovalProtocol": {
|
||||
"enum": [
|
||||
"http",
|
||||
|
||||
Generated
+6
-6
@@ -27,7 +27,7 @@
|
||||
"read": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -37,7 +37,7 @@
|
||||
"write": {
|
||||
"description": "This will be removed in favor of `entries`.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": [
|
||||
"array",
|
||||
@@ -58,9 +58,6 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ApiPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"FileSystemAccessMode": {
|
||||
"enum": [
|
||||
"read",
|
||||
@@ -74,7 +71,7 @@
|
||||
{
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/definitions/ApiPathString"
|
||||
"$ref": "#/definitions/LegacyAppPathString"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
@@ -529,6 +526,9 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"LegacyAppPathString": {
|
||||
"type": "string"
|
||||
},
|
||||
"NetworkApprovalProtocol": {
|
||||
"enum": [
|
||||
"http",
|
||||
|
||||
+1
-1
@@ -23,4 +23,4 @@
|
||||
* [`AbsolutePathBuf`]. Relative path text remains valid until an operation
|
||||
* such as [`Self::to_path_uri`] requires an absolute path.
|
||||
*/
|
||||
export type ApiPathString = string;
|
||||
export type LegacyAppPathString = string;
|
||||
+1
-1
@@ -4,7 +4,6 @@ export type { AbsolutePathBuf } from "./AbsolutePathBuf";
|
||||
export type { AgentMessageInputContent } from "./AgentMessageInputContent";
|
||||
export type { AgentPath } from "./AgentPath";
|
||||
export type { AmazonBedrockCredentialSource } from "./AmazonBedrockCredentialSource";
|
||||
export type { ApiPathString } from "./ApiPathString";
|
||||
export type { ApplyPatchApprovalParams } from "./ApplyPatchApprovalParams";
|
||||
export type { ApplyPatchApprovalResponse } from "./ApplyPatchApprovalResponse";
|
||||
export type { AuthMode } from "./AuthMode";
|
||||
@@ -43,6 +42,7 @@ export type { InitializeParams } from "./InitializeParams";
|
||||
export type { InitializeResponse } from "./InitializeResponse";
|
||||
export type { InputModality } from "./InputModality";
|
||||
export type { InternalSessionSource } from "./InternalSessionSource";
|
||||
export type { LegacyAppPathString } from "./LegacyAppPathString";
|
||||
export type { LocalShellAction } from "./LocalShellAction";
|
||||
export type { LocalShellExecAction } from "./LocalShellExecAction";
|
||||
export type { LocalShellStatus } from "./LocalShellStatus";
|
||||
|
||||
+3
-3
@@ -1,15 +1,15 @@
|
||||
// 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 { ApiPathString } from "../ApiPathString";
|
||||
import type { LegacyAppPathString } from "../LegacyAppPathString";
|
||||
import type { FileSystemSandboxEntry } from "./FileSystemSandboxEntry";
|
||||
|
||||
export type AdditionalFileSystemPermissions = {
|
||||
/**
|
||||
* This will be removed in favor of `entries`.
|
||||
*/
|
||||
read: Array<ApiPathString> | null,
|
||||
read: Array<LegacyAppPathString> | null,
|
||||
/**
|
||||
* This will be removed in favor of `entries`.
|
||||
*/
|
||||
write: Array<ApiPathString> | null, globScanMaxDepth?: number, entries?: Array<FileSystemSandboxEntry>, };
|
||||
write: Array<LegacyAppPathString> | null, globScanMaxDepth?: number, entries?: Array<FileSystemSandboxEntry>, };
|
||||
|
||||
@@ -1,7 +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 { ApiPathString } from "../ApiPathString";
|
||||
import type { LegacyAppPathString } from "../LegacyAppPathString";
|
||||
import type { FileSystemSpecialPath } from "./FileSystemSpecialPath";
|
||||
|
||||
export type FileSystemPath = { "type": "path", path: ApiPathString, } | { "type": "glob_pattern", pattern: string, } | { "type": "special", value: FileSystemSpecialPath, };
|
||||
export type FileSystemPath = { "type": "path", path: LegacyAppPathString, } | { "type": "glob_pattern", pattern: string, } | { "type": "special", value: FileSystemSpecialPath, };
|
||||
|
||||
@@ -16,7 +16,7 @@ use codex_protocol::protocol::NetworkAccess as CoreNetworkAccess;
|
||||
use codex_protocol::request_permissions::PermissionGrantScope as CorePermissionGrantScope;
|
||||
use codex_protocol::request_permissions::RequestPermissionProfile as CoreRequestPermissionProfile;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::ApiPathString;
|
||||
use codex_utils_path_uri::LegacyAppPathString;
|
||||
use codex_utils_path_uri::PathConvention;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
@@ -57,9 +57,9 @@ impl From<CoreNetworkApprovalContext> for NetworkApprovalContext {
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct AdditionalFileSystemPermissions {
|
||||
/// This will be removed in favor of `entries`.
|
||||
pub read: Option<Vec<ApiPathString>>,
|
||||
pub read: Option<Vec<LegacyAppPathString>>,
|
||||
/// This will be removed in favor of `entries`.
|
||||
pub write: Option<Vec<ApiPathString>>,
|
||||
pub write: Option<Vec<LegacyAppPathString>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub glob_scan_max_depth: Option<NonZeroUsize>,
|
||||
@@ -78,7 +78,7 @@ impl From<CoreFileSystemPermissions<AbsolutePathBuf>> for AdditionalFileSystemPe
|
||||
if let Some(paths) = read.as_ref() {
|
||||
entries.extend(paths.iter().map(|path| FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: ApiPathString::from_abs_path(path),
|
||||
path: LegacyAppPathString::from_abs_path(path),
|
||||
},
|
||||
access: FileSystemAccessMode::Read,
|
||||
}));
|
||||
@@ -86,14 +86,24 @@ impl From<CoreFileSystemPermissions<AbsolutePathBuf>> for AdditionalFileSystemPe
|
||||
if let Some(paths) = write.as_ref() {
|
||||
entries.extend(paths.iter().map(|path| FileSystemSandboxEntry {
|
||||
path: FileSystemPath::Path {
|
||||
path: ApiPathString::from_abs_path(path),
|
||||
path: LegacyAppPathString::from_abs_path(path),
|
||||
},
|
||||
access: FileSystemAccessMode::Write,
|
||||
}));
|
||||
}
|
||||
Self {
|
||||
read: read.map(|paths| paths.iter().map(ApiPathString::from_abs_path).collect()),
|
||||
write: write.map(|paths| paths.iter().map(ApiPathString::from_abs_path).collect()),
|
||||
read: read.map(|paths| {
|
||||
paths
|
||||
.iter()
|
||||
.map(LegacyAppPathString::from_abs_path)
|
||||
.collect()
|
||||
}),
|
||||
write: write.map(|paths| {
|
||||
paths
|
||||
.iter()
|
||||
.map(LegacyAppPathString::from_abs_path)
|
||||
.collect()
|
||||
}),
|
||||
glob_scan_max_depth: None,
|
||||
entries: Some(entries),
|
||||
}
|
||||
@@ -276,7 +286,7 @@ impl From<FileSystemSpecialPath> for CoreFileSystemSpecialPath {
|
||||
#[ts(export_to = "v2/")]
|
||||
// TODO(anp): Rename this type to distinguish it from the generic protocol FileSystemPath.
|
||||
pub enum FileSystemPath {
|
||||
Path { path: ApiPathString },
|
||||
Path { path: LegacyAppPathString },
|
||||
GlobPattern { pattern: String },
|
||||
Special { value: FileSystemSpecialPath },
|
||||
}
|
||||
@@ -286,7 +296,7 @@ impl From<CoreFileSystemPath<AbsolutePathBuf>> for FileSystemPath {
|
||||
fn from(value: CoreFileSystemPath<AbsolutePathBuf>) -> Self {
|
||||
match value {
|
||||
CoreFileSystemPath::Path { path } => Self::Path {
|
||||
path: ApiPathString::from_abs_path(&path),
|
||||
path: LegacyAppPathString::from_abs_path(&path),
|
||||
},
|
||||
CoreFileSystemPath::GlobPattern { pattern } => Self::GlobPattern { pattern },
|
||||
CoreFileSystemPath::Special { value } => Self::Special {
|
||||
|
||||
@@ -35,7 +35,7 @@ use codex_protocol::user_input::UserInput as CoreUserInput;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_absolute_path::test_support::PathBufExt;
|
||||
use codex_utils_absolute_path::test_support::test_path_buf;
|
||||
use codex_utils_path_uri::ApiPathString;
|
||||
use codex_utils_path_uri::LegacyAppPathString;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value as JsonValue;
|
||||
use serde_json::json;
|
||||
@@ -579,8 +579,8 @@ fn additional_file_system_permissions_populates_entries_for_legacy_roots() {
|
||||
);
|
||||
|
||||
let permissions = AdditionalFileSystemPermissions::from(core_permissions.clone());
|
||||
let read_only_api_path = ApiPathString::from_abs_path(&read_only_path);
|
||||
let read_write_api_path = ApiPathString::from_abs_path(&read_write_path);
|
||||
let read_only_api_path = LegacyAppPathString::from_abs_path(&read_only_path);
|
||||
let read_write_api_path = LegacyAppPathString::from_abs_path(&read_write_path);
|
||||
|
||||
assert_eq!(
|
||||
permissions,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_utils_path_uri::ApiPathString;
|
||||
use codex_utils_path_uri::LegacyAppPathString;
|
||||
use codex_utils_path_uri::PathConvention;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
|
||||
@@ -28,7 +28,7 @@ impl TestEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remote_cwd(&self, instance_id: &str) -> Result<Option<ApiPathString>> {
|
||||
pub(crate) fn remote_cwd(&self, instance_id: &str) -> Result<Option<LegacyAppPathString>> {
|
||||
let path_uri = match self {
|
||||
Self::Local => return Ok(None),
|
||||
Self::Docker { .. } => {
|
||||
@@ -40,7 +40,7 @@ impl TestEnvironment {
|
||||
PathUri::parse(&format!("file:///C:/codex-core-test-cwd-{instance_id}"))?
|
||||
}
|
||||
};
|
||||
Ok(Some(ApiPathString::from_path_uri(
|
||||
Ok(Some(LegacyAppPathString::from_path_uri(
|
||||
&path_uri,
|
||||
self.path_convention(),
|
||||
)?))
|
||||
|
||||
@@ -164,7 +164,7 @@ pub(super) use codex_terminal_detection::TerminalInfo;
|
||||
pub(super) use codex_terminal_detection::TerminalName;
|
||||
pub(super) use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
pub(super) use codex_utils_approval_presets::builtin_approval_presets;
|
||||
pub(super) use codex_utils_path_uri::ApiPathString;
|
||||
pub(super) use codex_utils_path_uri::LegacyAppPathString;
|
||||
pub(super) use crossterm::event::KeyCode;
|
||||
pub(super) use crossterm::event::KeyEvent;
|
||||
pub(super) use crossterm::event::KeyModifiers;
|
||||
|
||||
@@ -89,8 +89,8 @@ fn app_server_exec_approval_request_preserves_permissions_context() {
|
||||
.expect("absolute read path");
|
||||
let write_path = AbsolutePathBuf::try_from(PathBuf::from(test_path_display("/tmp/write")))
|
||||
.expect("absolute write path");
|
||||
let read_api_path = ApiPathString::from_abs_path(&read_path);
|
||||
let write_api_path = ApiPathString::from_abs_path(&write_path);
|
||||
let read_api_path = LegacyAppPathString::from_abs_path(&read_path);
|
||||
let write_api_path = LegacyAppPathString::from_abs_path(&write_path);
|
||||
let request = exec_approval_request_from_params(
|
||||
AppServerCommandExecutionRequestApprovalParams {
|
||||
thread_id: "thread-1".to_string(),
|
||||
@@ -276,8 +276,8 @@ fn app_server_request_permissions_preserves_file_system_permissions() {
|
||||
.expect("absolute read path");
|
||||
let write_path = AbsolutePathBuf::try_from(PathBuf::from(test_path_display("/tmp/write")))
|
||||
.expect("absolute write path");
|
||||
let read_api_path = ApiPathString::from_abs_path(&read_path);
|
||||
let write_api_path = ApiPathString::from_abs_path(&write_path);
|
||||
let read_api_path = LegacyAppPathString::from_abs_path(&read_path);
|
||||
let write_api_path = LegacyAppPathString::from_abs_path(&write_path);
|
||||
let cwd =
|
||||
AbsolutePathBuf::try_from(PathBuf::from(test_path_display("/tmp"))).expect("absolute cwd");
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ use ts_rs::TS;
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize, TS)]
|
||||
#[serde(transparent)]
|
||||
#[ts(type = "string")]
|
||||
pub struct ApiPathString(String);
|
||||
pub struct LegacyAppPathString(String);
|
||||
|
||||
impl ApiPathString {
|
||||
impl LegacyAppPathString {
|
||||
/// Renders an absolute path using the current host's path convention.
|
||||
pub fn from_abs_path(path: &AbsolutePathBuf) -> Self {
|
||||
Self(path.to_string_lossy().into_owned())
|
||||
@@ -48,7 +48,7 @@ impl ApiPathString {
|
||||
pub fn from_path_uri(
|
||||
path: &PathUri,
|
||||
convention: PathConvention,
|
||||
) -> Result<Self, ApiPathStringError> {
|
||||
) -> Result<Self, LegacyAppPathStringError> {
|
||||
if let Some(path_bytes) = path.opaque_fallback_bytes() {
|
||||
return render_opaque_fallback(path, &path_bytes, convention).map(Self);
|
||||
}
|
||||
@@ -61,12 +61,15 @@ impl ApiPathString {
|
||||
|
||||
/// Parses this API string as an absolute path using the requested native
|
||||
/// path convention and returns its canonical path URI.
|
||||
pub fn to_path_uri(&self, convention: PathConvention) -> Result<PathUri, ApiPathStringError> {
|
||||
pub fn to_path_uri(
|
||||
&self,
|
||||
convention: PathConvention,
|
||||
) -> Result<PathUri, LegacyAppPathStringError> {
|
||||
let path = match convention {
|
||||
PathConvention::Posix => parse_posix_path(&self.0),
|
||||
PathConvention::Windows => parse_windows_path(&self.0),
|
||||
};
|
||||
path.ok_or_else(|| ApiPathStringError::InvalidNativePath {
|
||||
path.ok_or_else(|| LegacyAppPathStringError::InvalidNativePath {
|
||||
path: self.0.clone(),
|
||||
convention,
|
||||
})
|
||||
@@ -102,7 +105,7 @@ impl ApiPathString {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AbsolutePathBuf> for ApiPathString {
|
||||
impl From<AbsolutePathBuf> for LegacyAppPathString {
|
||||
fn from(path: AbsolutePathBuf) -> Self {
|
||||
Self::from_abs_path(&path)
|
||||
}
|
||||
@@ -194,7 +197,7 @@ fn render_opaque_fallback(
|
||||
path: &PathUri,
|
||||
path_bytes: &[u8],
|
||||
convention: PathConvention,
|
||||
) -> Result<String, ApiPathStringError> {
|
||||
) -> Result<String, LegacyAppPathStringError> {
|
||||
let rendered = match convention {
|
||||
PathConvention::Posix if path_bytes.starts_with(b"/") => {
|
||||
Some(String::from_utf8_lossy(path_bytes).into_owned())
|
||||
@@ -202,7 +205,7 @@ fn render_opaque_fallback(
|
||||
PathConvention::Windows => render_windows_opaque_fallback(path_bytes),
|
||||
PathConvention::Posix => None,
|
||||
};
|
||||
rendered.ok_or_else(|| ApiPathStringError::OpaqueFallback {
|
||||
rendered.ok_or_else(|| LegacyAppPathStringError::OpaqueFallback {
|
||||
path: path.to_string(),
|
||||
})
|
||||
}
|
||||
@@ -238,13 +241,13 @@ fn is_windows_separator(character: u16) -> bool {
|
||||
character == u16::from(b'\\') || character == u16::from(b'/')
|
||||
}
|
||||
|
||||
impl fmt::Display for ApiPathString {
|
||||
impl fmt::Display for LegacyAppPathString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for ApiPathString {
|
||||
impl Serialize for LegacyAppPathString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
@@ -253,9 +256,9 @@ impl Serialize for ApiPathString {
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for ApiPathString {
|
||||
impl JsonSchema for LegacyAppPathString {
|
||||
fn schema_name() -> String {
|
||||
"ApiPathString".to_string()
|
||||
"LegacyAppPathString".to_string()
|
||||
}
|
||||
|
||||
fn json_schema(generator: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||
@@ -263,7 +266,7 @@ impl JsonSchema for ApiPathString {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_posix_path(path: &PathUri) -> Result<String, ApiPathStringError> {
|
||||
fn render_posix_path(path: &PathUri) -> Result<String, LegacyAppPathStringError> {
|
||||
let url = path.to_url();
|
||||
// POSIX file paths do not have a UNC authority, so `file://server/share`
|
||||
// cannot be represented as `/share` without losing the server identity.
|
||||
@@ -281,7 +284,7 @@ fn render_posix_path(path: &PathUri) -> Result<String, ApiPathStringError> {
|
||||
Ok(rendered)
|
||||
}
|
||||
|
||||
fn render_windows_path(path: &PathUri) -> Result<String, ApiPathStringError> {
|
||||
fn render_windows_path(path: &PathUri) -> Result<String, LegacyAppPathStringError> {
|
||||
let url = path.to_url();
|
||||
let mut segments = path_segments(&url);
|
||||
let mut rendered = String::new();
|
||||
@@ -342,15 +345,15 @@ fn decode_native_segment(segment: &str) -> String {
|
||||
String::from_utf8_lossy(&bytes).into_owned()
|
||||
}
|
||||
|
||||
fn incompatible_convention(path: &PathUri, convention: PathConvention) -> ApiPathStringError {
|
||||
ApiPathStringError::IncompatibleConvention {
|
||||
fn incompatible_convention(path: &PathUri, convention: PathConvention) -> LegacyAppPathStringError {
|
||||
LegacyAppPathStringError::IncompatibleConvention {
|
||||
path: path.to_string(),
|
||||
convention,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error, PartialEq, Eq)]
|
||||
pub enum ApiPathStringError {
|
||||
pub enum LegacyAppPathStringError {
|
||||
#[error("opaque fallback path URI `{path}` cannot be recovered as a native path")]
|
||||
OpaqueFallback { path: String },
|
||||
#[error("path URI `{path}` cannot be rendered using {convention} path syntax")]
|
||||
|
||||
@@ -301,21 +301,23 @@ fn renders_native_paths_from_shared_cases() {
|
||||
for case in RENDER_CASES {
|
||||
let path = PathUri::parse(case.uri).expect("valid file URI");
|
||||
let expected = match case.expected {
|
||||
RenderExpectation::RoundTrip(rendered) => Ok(ApiPathString(rendered.to_string())),
|
||||
RenderExpectation::RenderOnly(rendered) => Ok(ApiPathString(rendered.to_string())),
|
||||
RenderExpectation::RoundTrip(rendered) => Ok(LegacyAppPathString(rendered.to_string())),
|
||||
RenderExpectation::RenderOnly(rendered) => {
|
||||
Ok(LegacyAppPathString(rendered.to_string()))
|
||||
}
|
||||
RenderExpectation::Error(ExpectedError::OpaqueFallback) => {
|
||||
Err(ApiPathStringError::OpaqueFallback {
|
||||
Err(LegacyAppPathStringError::OpaqueFallback {
|
||||
path: path.to_string(),
|
||||
})
|
||||
}
|
||||
RenderExpectation::Error(ExpectedError::IncompatibleConvention) => {
|
||||
Err(ApiPathStringError::IncompatibleConvention {
|
||||
Err(LegacyAppPathStringError::IncompatibleConvention {
|
||||
path: path.to_string(),
|
||||
convention: case.convention,
|
||||
})
|
||||
}
|
||||
};
|
||||
let actual = ApiPathString::from_path_uri(&path, case.convention);
|
||||
let actual = LegacyAppPathString::from_path_uri(&path, case.convention);
|
||||
|
||||
assert_eq!(actual, expected, "rendering {case:?}");
|
||||
if let Ok(rendered) = &actual {
|
||||
@@ -327,14 +329,15 @@ fn renders_native_paths_from_shared_cases() {
|
||||
}
|
||||
|
||||
if let RenderExpectation::RoundTrip(rendered) = case.expected {
|
||||
let api_path = serde_json::from_value::<ApiPathString>(serde_json::json!(rendered))
|
||||
.expect("native path should deserialize from API text");
|
||||
let api_path =
|
||||
serde_json::from_value::<LegacyAppPathString>(serde_json::json!(rendered))
|
||||
.expect("native path should deserialize from API text");
|
||||
let reparsed = api_path
|
||||
.to_path_uri(case.convention)
|
||||
.expect("native path should parse using its convention");
|
||||
assert_eq!(reparsed, path, "parsing {case:?}");
|
||||
assert_eq!(
|
||||
ApiPathString::from_path_uri(&reparsed, case.convention),
|
||||
LegacyAppPathString::from_path_uri(&reparsed, case.convention),
|
||||
Ok(api_path),
|
||||
"round-tripping {case:?}"
|
||||
);
|
||||
@@ -345,7 +348,7 @@ fn renders_native_paths_from_shared_cases() {
|
||||
#[test]
|
||||
fn relative_api_path_serializes_and_deserializes_unchanged() {
|
||||
for raw_path in [".", "subdir", "subdir/file.rs"] {
|
||||
let path = serde_json::from_value::<ApiPathString>(serde_json::json!(raw_path))
|
||||
let path = serde_json::from_value::<LegacyAppPathString>(serde_json::json!(raw_path))
|
||||
.expect("relative API path should deserialize");
|
||||
|
||||
assert_eq!(
|
||||
@@ -358,13 +361,13 @@ fn relative_api_path_serializes_and_deserializes_unchanged() {
|
||||
#[test]
|
||||
fn relative_api_path_is_invalid_when_converted_to_a_path_uri() {
|
||||
let raw_path = "subdir";
|
||||
let path = serde_json::from_value::<ApiPathString>(serde_json::json!(raw_path))
|
||||
let path = serde_json::from_value::<LegacyAppPathString>(serde_json::json!(raw_path))
|
||||
.expect("relative API path should deserialize");
|
||||
|
||||
assert_eq!(path.infer_absolute_path_convention(), None);
|
||||
assert_eq!(
|
||||
path.to_path_uri(PathConvention::Posix),
|
||||
Err(ApiPathStringError::InvalidNativePath {
|
||||
Err(LegacyAppPathStringError::InvalidNativePath {
|
||||
path: raw_path.to_string(),
|
||||
convention: PathConvention::Posix,
|
||||
})
|
||||
@@ -377,13 +380,13 @@ fn other_non_absolute_api_paths_cannot_be_converted_to_path_uris() {
|
||||
(r"workspace\file.rs", PathConvention::Windows),
|
||||
(r"C:file.rs", PathConvention::Windows),
|
||||
] {
|
||||
let path = serde_json::from_value::<ApiPathString>(serde_json::json!(raw_path))
|
||||
let path = serde_json::from_value::<LegacyAppPathString>(serde_json::json!(raw_path))
|
||||
.expect("API path should deserialize without validation");
|
||||
|
||||
assert_eq!(path.infer_absolute_path_convention(), None);
|
||||
assert_eq!(
|
||||
path.to_path_uri(convention),
|
||||
Err(ApiPathStringError::InvalidNativePath {
|
||||
Err(LegacyAppPathStringError::InvalidNativePath {
|
||||
path: raw_path.to_string(),
|
||||
convention,
|
||||
})
|
||||
@@ -409,7 +412,7 @@ fn infers_absolute_path_conventions_from_api_text() {
|
||||
(r"C:file.rs", None),
|
||||
(r"\rooted-without-drive", None),
|
||||
] {
|
||||
let path = serde_json::from_value::<ApiPathString>(serde_json::json!(raw_path))
|
||||
let path = serde_json::from_value::<LegacyAppPathString>(serde_json::json!(raw_path))
|
||||
.expect("API path should deserialize without validation");
|
||||
|
||||
assert_eq!(
|
||||
@@ -426,7 +429,7 @@ fn foreign_absolute_syntax_deserializes_without_host_interpretation() {
|
||||
(r"C:\workspace\file.rs", PathConvention::Windows),
|
||||
("/workspace/file.rs", PathConvention::Posix),
|
||||
] {
|
||||
let path = serde_json::from_value::<ApiPathString>(serde_json::json!(raw_path))
|
||||
let path = serde_json::from_value::<LegacyAppPathString>(serde_json::json!(raw_path))
|
||||
.expect("foreign API path should deserialize");
|
||||
|
||||
assert_eq!(path.as_str(), raw_path);
|
||||
@@ -444,8 +447,8 @@ fn renders_an_absolute_path_using_the_host_convention() {
|
||||
.expect("native path should be absolute");
|
||||
|
||||
assert_eq!(
|
||||
ApiPathString::from(path),
|
||||
ApiPathString(native_path.to_string())
|
||||
LegacyAppPathString::from(path),
|
||||
LegacyAppPathString(native_path.to_string())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -464,19 +467,19 @@ fn renders_native_non_unicode_windows_fallback_lossily() {
|
||||
AbsolutePathBuf::from_absolute_path_checked(native_path).expect("absolute native path");
|
||||
|
||||
assert_eq!(
|
||||
ApiPathString::from_abs_path(&native_path),
|
||||
ApiPathString(r"C:\bad\�".to_string())
|
||||
LegacyAppPathString::from_abs_path(&native_path),
|
||||
LegacyAppPathString(r"C:\bad\�".to_string())
|
||||
);
|
||||
|
||||
let path = PathUri::from_abs_path(&native_path);
|
||||
|
||||
assert_eq!(
|
||||
ApiPathString::from_path_uri(&path, PathConvention::Windows),
|
||||
Ok(ApiPathString(r"C:\bad\�".to_string()))
|
||||
LegacyAppPathString::from_path_uri(&path, PathConvention::Windows),
|
||||
Ok(LegacyAppPathString(r"C:\bad\�".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
ApiPathString::from_path_uri(&path, PathConvention::Posix),
|
||||
Err(ApiPathStringError::OpaqueFallback {
|
||||
LegacyAppPathString::from_path_uri(&path, PathConvention::Posix),
|
||||
Err(LegacyAppPathStringError::OpaqueFallback {
|
||||
path: path.to_string(),
|
||||
})
|
||||
);
|
||||
@@ -485,13 +488,13 @@ fn renders_native_non_unicode_windows_fallback_lossily() {
|
||||
#[test]
|
||||
fn serializes_and_deserializes_as_a_string() {
|
||||
let path = PathUri::parse("file:///workspace/src/lib.rs").expect("valid file URI");
|
||||
let rendered = ApiPathString::from_path_uri(&path, PathConvention::Posix)
|
||||
let rendered = LegacyAppPathString::from_path_uri(&path, PathConvention::Posix)
|
||||
.expect("POSIX URI should render");
|
||||
|
||||
let json = serde_json::to_string(&rendered).expect("rendered path should serialize");
|
||||
assert_eq!(json, r#""/workspace/src/lib.rs""#);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<ApiPathString>(&json)
|
||||
serde_json::from_str::<LegacyAppPathString>(&json)
|
||||
.expect("rendered path should deserialize from a string"),
|
||||
rendered
|
||||
);
|
||||
|
||||
@@ -19,8 +19,8 @@ use url::Url;
|
||||
|
||||
mod api_path_string;
|
||||
|
||||
pub use api_path_string::ApiPathString;
|
||||
pub use api_path_string::ApiPathStringError;
|
||||
pub use api_path_string::LegacyAppPathString;
|
||||
pub use api_path_string::LegacyAppPathStringError;
|
||||
pub use api_path_string::PathConvention;
|
||||
|
||||
pub const FILE_SCHEME: &str = "file";
|
||||
|
||||
Reference in New Issue
Block a user