feat: add APIs to list and download public remote skills (#10448)
Add API to list / download from remote public skills
This commit is contained in:
parent
08926a3fb7
commit
f38d181795
38 changed files with 1508 additions and 2 deletions
124
codex-rs/Cargo.lock
generated
124
codex-rs/Cargo.lock
generated
|
|
@ -398,6 +398,15 @@ dependencies = [
|
|||
"wiremock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arboard"
|
||||
version = "3.6.1"
|
||||
|
|
@ -924,6 +933,25 @@ dependencies = [
|
|||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47"
|
||||
dependencies = [
|
||||
"bzip2-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bzip2-sys"
|
||||
version = "0.1.13+1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cassowary"
|
||||
version = "0.3.0"
|
||||
|
|
@ -1578,6 +1606,7 @@ dependencies = [
|
|||
"which",
|
||||
"wildmatch",
|
||||
"wiremock",
|
||||
"zip",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
|
|
@ -2353,6 +2382,12 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
|
|
@ -2771,6 +2806,12 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate64"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26bf8fc351c5ed29b5c2f0cbbac1b209b74f60ecd62e675a998df72c49af5204"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
|
|
@ -2803,6 +2844,17 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "1.0.0"
|
||||
|
|
@ -4929,6 +4981,27 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-rs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-sys"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
|
|
@ -10515,6 +10588,15 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xz2"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
|
||||
dependencies = [
|
||||
"lzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
|
|
@ -10701,12 +10783,54 @@ dependencies = [
|
|||
"syn 2.0.114",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "2.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"arbitrary",
|
||||
"bzip2",
|
||||
"constant_time_eq",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"deflate64",
|
||||
"displaydoc",
|
||||
"flate2",
|
||||
"getrandom 0.3.4",
|
||||
"hmac",
|
||||
"indexmap 2.13.0",
|
||||
"lzma-rs",
|
||||
"memchr",
|
||||
"pbkdf2",
|
||||
"sha1",
|
||||
"thiserror 2.0.18",
|
||||
"time",
|
||||
"xz2",
|
||||
"zeroize",
|
||||
"zopfli",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"crc32fast",
|
||||
"log",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.13.3"
|
||||
|
|
|
|||
|
|
@ -249,6 +249,7 @@ walkdir = "2.5.0"
|
|||
webbrowser = "1.0"
|
||||
which = "8"
|
||||
wildmatch = "2.6.1"
|
||||
zip = "2.4.2"
|
||||
|
||||
wiremock = "0.6"
|
||||
zeroize = "1.8.2"
|
||||
|
|
|
|||
|
|
@ -2183,6 +2183,24 @@
|
|||
},
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteReadParams": {
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteWriteParams": {
|
||||
"properties": {
|
||||
"hazelnutId": {
|
||||
"type": "string"
|
||||
},
|
||||
"isPreload": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"hazelnutId",
|
||||
"isPreload"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"TextElement": {
|
||||
"properties": {
|
||||
"byteRange": {
|
||||
|
|
@ -3312,6 +3330,54 @@
|
|||
"title": "Skills/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"skills/remote/read"
|
||||
],
|
||||
"title": "Skills/remote/readRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/SkillsRemoteReadParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Skills/remote/readRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"skills/remote/write"
|
||||
],
|
||||
"title": "Skills/remote/writeRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/SkillsRemoteWriteParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Skills/remote/writeRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
|
|
|
|||
|
|
@ -2012,6 +2012,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -3429,6 +3482,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
@ -6536,6 +6608,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -2590,6 +2590,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -4469,6 +4522,25 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -718,6 +718,54 @@
|
|||
"title": "Skills/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"skills/remote/read"
|
||||
],
|
||||
"title": "Skills/remote/readRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/SkillsRemoteReadParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Skills/remote/readRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"skills/remote/write"
|
||||
],
|
||||
"title": "Skills/remote/writeRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/SkillsRemoteWriteParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Skills/remote/writeRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
|
|
@ -3852,6 +3900,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -6351,6 +6452,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RemoveConversationListenerParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
|
@ -12382,6 +12502,25 @@
|
|||
"title": "ReasoningTextDeltaNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ResidencyRequirement": {
|
||||
"enum": [
|
||||
"us"
|
||||
|
|
@ -13417,6 +13556,65 @@
|
|||
"title": "SkillsListResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteReadParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "SkillsRemoteReadParams",
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteReadResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"data": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"title": "SkillsRemoteReadResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteWriteParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"hazelnutId": {
|
||||
"type": "string"
|
||||
},
|
||||
"isPreload": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"hazelnutId",
|
||||
"isPreload"
|
||||
],
|
||||
"title": "SkillsRemoteWriteParams",
|
||||
"type": "object"
|
||||
},
|
||||
"SkillsRemoteWriteResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path"
|
||||
],
|
||||
"title": "SkillsRemoteWriteResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"SubAgentSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2012,6 +2012,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -3429,6 +3482,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2012,6 +2012,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -3429,6 +3482,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2012,6 +2012,59 @@
|
|||
"title": "ListSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "List of remote skills available to the agent.",
|
||||
"properties": {
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"list_remote_skills_response"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"skills",
|
||||
"type"
|
||||
],
|
||||
"title": "ListRemoteSkillsResponseEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Remote skill downloaded to local cache.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote_skill_downloaded"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsgType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"title": "RemoteSkillDownloadedEventMsg",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"description": "Notification that skill data may have been updated and clients may want to reload.",
|
||||
"properties": {
|
||||
|
|
@ -3429,6 +3482,25 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"RequestId": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "SkillsRemoteReadParams",
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"RemoteSkillSummary": {
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"data": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteSkillSummary"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data"
|
||||
],
|
||||
"title": "SkillsRemoteReadResponse",
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"hazelnutId": {
|
||||
"type": "string"
|
||||
},
|
||||
"isPreload": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"hazelnutId",
|
||||
"isPreload"
|
||||
],
|
||||
"title": "SkillsRemoteWriteParams",
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"name",
|
||||
"path"
|
||||
],
|
||||
"title": "SkillsRemoteWriteResponse",
|
||||
"type": "object"
|
||||
}
|
||||
|
|
@ -36,6 +36,8 @@ import type { ModelListParams } from "./v2/ModelListParams";
|
|||
import type { ReviewStartParams } from "./v2/ReviewStartParams";
|
||||
import type { SkillsConfigWriteParams } from "./v2/SkillsConfigWriteParams";
|
||||
import type { SkillsListParams } from "./v2/SkillsListParams";
|
||||
import type { SkillsRemoteReadParams } from "./v2/SkillsRemoteReadParams";
|
||||
import type { SkillsRemoteWriteParams } from "./v2/SkillsRemoteWriteParams";
|
||||
import type { ThreadArchiveParams } from "./v2/ThreadArchiveParams";
|
||||
import type { ThreadForkParams } from "./v2/ThreadForkParams";
|
||||
import type { ThreadListParams } from "./v2/ThreadListParams";
|
||||
|
|
@ -52,4 +54,4 @@ import type { TurnStartParams } from "./v2/TurnStartParams";
|
|||
/**
|
||||
* Request from the client to the server.
|
||||
*/
|
||||
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "newConversation", id: RequestId, params: NewConversationParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "listConversations", id: RequestId, params: ListConversationsParams, } | { "method": "resumeConversation", id: RequestId, params: ResumeConversationParams, } | { "method": "forkConversation", id: RequestId, params: ForkConversationParams, } | { "method": "archiveConversation", id: RequestId, params: ArchiveConversationParams, } | { "method": "sendUserMessage", id: RequestId, params: SendUserMessageParams, } | { "method": "sendUserTurn", id: RequestId, params: SendUserTurnParams, } | { "method": "interruptConversation", id: RequestId, params: InterruptConversationParams, } | { "method": "addConversationListener", id: RequestId, params: AddConversationListenerParams, } | { "method": "removeConversationListener", id: RequestId, params: RemoveConversationListenerParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "loginApiKey", id: RequestId, params: LoginApiKeyParams, } | { "method": "loginChatGpt", id: RequestId, params: undefined, } | { "method": "cancelLoginChatGpt", id: RequestId, params: CancelLoginChatGptParams, } | { "method": "logoutChatGpt", id: RequestId, params: undefined, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "getUserSavedConfig", id: RequestId, params: undefined, } | { "method": "setDefaultModel", id: RequestId, params: SetDefaultModelParams, } | { "method": "getUserAgent", id: RequestId, params: undefined, } | { "method": "userInfo", id: RequestId, params: undefined, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, } | { "method": "execOneOffCommand", id: RequestId, params: ExecOneOffCommandParams, };
|
||||
export type ClientRequest ={ "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/name/set", id: RequestId, params: ThreadSetNameParams, } | { "method": "thread/unarchive", id: RequestId, params: ThreadUnarchiveParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "thread/read", id: RequestId, params: ThreadReadParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "skills/remote/read", id: RequestId, params: SkillsRemoteReadParams, } | { "method": "skills/remote/write", id: RequestId, params: SkillsRemoteWriteParams, } | { "method": "app/list", id: RequestId, params: AppsListParams, } | { "method": "skills/config/write", id: RequestId, params: SkillsConfigWriteParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "newConversation", id: RequestId, params: NewConversationParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "listConversations", id: RequestId, params: ListConversationsParams, } | { "method": "resumeConversation", id: RequestId, params: ResumeConversationParams, } | { "method": "forkConversation", id: RequestId, params: ForkConversationParams, } | { "method": "archiveConversation", id: RequestId, params: ArchiveConversationParams, } | { "method": "sendUserMessage", id: RequestId, params: SendUserMessageParams, } | { "method": "sendUserTurn", id: RequestId, params: SendUserTurnParams, } | { "method": "interruptConversation", id: RequestId, params: InterruptConversationParams, } | { "method": "addConversationListener", id: RequestId, params: AddConversationListenerParams, } | { "method": "removeConversationListener", id: RequestId, params: RemoveConversationListenerParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "loginApiKey", id: RequestId, params: LoginApiKeyParams, } | { "method": "loginChatGpt", id: RequestId, params: undefined, } | { "method": "cancelLoginChatGpt", id: RequestId, params: CancelLoginChatGptParams, } | { "method": "logoutChatGpt", id: RequestId, params: undefined, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "getUserSavedConfig", id: RequestId, params: undefined, } | { "method": "setDefaultModel", id: RequestId, params: SetDefaultModelParams, } | { "method": "getUserAgent", id: RequestId, params: undefined, } | { "method": "userInfo", id: RequestId, params: undefined, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, } | { "method": "execOneOffCommand", id: RequestId, params: ExecOneOffCommandParams, };
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import type { GetHistoryEntryResponseEvent } from "./GetHistoryEntryResponseEven
|
|||
import type { ItemCompletedEvent } from "./ItemCompletedEvent";
|
||||
import type { ItemStartedEvent } from "./ItemStartedEvent";
|
||||
import type { ListCustomPromptsResponseEvent } from "./ListCustomPromptsResponseEvent";
|
||||
import type { ListRemoteSkillsResponseEvent } from "./ListRemoteSkillsResponseEvent";
|
||||
import type { ListSkillsResponseEvent } from "./ListSkillsResponseEvent";
|
||||
import type { McpListToolsResponseEvent } from "./McpListToolsResponseEvent";
|
||||
import type { McpStartupCompleteEvent } from "./McpStartupCompleteEvent";
|
||||
|
|
@ -45,6 +46,7 @@ import type { PlanDeltaEvent } from "./PlanDeltaEvent";
|
|||
import type { RawResponseItemEvent } from "./RawResponseItemEvent";
|
||||
import type { ReasoningContentDeltaEvent } from "./ReasoningContentDeltaEvent";
|
||||
import type { ReasoningRawContentDeltaEvent } from "./ReasoningRawContentDeltaEvent";
|
||||
import type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
|
||||
import type { RequestUserInputEvent } from "./RequestUserInputEvent";
|
||||
import type { ReviewRequest } from "./ReviewRequest";
|
||||
import type { SessionConfiguredEvent } from "./SessionConfiguredEvent";
|
||||
|
|
@ -70,4 +72,4 @@ import type { WebSearchEndEvent } from "./WebSearchEndEvent";
|
|||
* Response event from the agent
|
||||
* NOTE: Make sure none of these values have optional types, as it will mess up the extension code-gen.
|
||||
*/
|
||||
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent;
|
||||
export type EventMsg = { "type": "error" } & ErrorEvent | { "type": "warning" } & WarningEvent | { "type": "context_compacted" } & ContextCompactedEvent | { "type": "thread_rolled_back" } & ThreadRolledBackEvent | { "type": "task_started" } & TurnStartedEvent | { "type": "task_complete" } & TurnCompleteEvent | { "type": "token_count" } & TokenCountEvent | { "type": "agent_message" } & AgentMessageEvent | { "type": "user_message" } & UserMessageEvent | { "type": "agent_message_delta" } & AgentMessageDeltaEvent | { "type": "agent_reasoning" } & AgentReasoningEvent | { "type": "agent_reasoning_delta" } & AgentReasoningDeltaEvent | { "type": "agent_reasoning_raw_content" } & AgentReasoningRawContentEvent | { "type": "agent_reasoning_raw_content_delta" } & AgentReasoningRawContentDeltaEvent | { "type": "agent_reasoning_section_break" } & AgentReasoningSectionBreakEvent | { "type": "session_configured" } & SessionConfiguredEvent | { "type": "thread_name_updated" } & ThreadNameUpdatedEvent | { "type": "mcp_startup_update" } & McpStartupUpdateEvent | { "type": "mcp_startup_complete" } & McpStartupCompleteEvent | { "type": "mcp_tool_call_begin" } & McpToolCallBeginEvent | { "type": "mcp_tool_call_end" } & McpToolCallEndEvent | { "type": "web_search_begin" } & WebSearchBeginEvent | { "type": "web_search_end" } & WebSearchEndEvent | { "type": "exec_command_begin" } & ExecCommandBeginEvent | { "type": "exec_command_output_delta" } & ExecCommandOutputDeltaEvent | { "type": "terminal_interaction" } & TerminalInteractionEvent | { "type": "exec_command_end" } & ExecCommandEndEvent | { "type": "view_image_tool_call" } & ViewImageToolCallEvent | { "type": "exec_approval_request" } & ExecApprovalRequestEvent | { "type": "request_user_input" } & RequestUserInputEvent | { "type": "dynamic_tool_call_request" } & DynamicToolCallRequest | { "type": "elicitation_request" } & ElicitationRequestEvent | { "type": "apply_patch_approval_request" } & ApplyPatchApprovalRequestEvent | { "type": "deprecation_notice" } & DeprecationNoticeEvent | { "type": "background_event" } & BackgroundEventEvent | { "type": "undo_started" } & UndoStartedEvent | { "type": "undo_completed" } & UndoCompletedEvent | { "type": "stream_error" } & StreamErrorEvent | { "type": "patch_apply_begin" } & PatchApplyBeginEvent | { "type": "patch_apply_end" } & PatchApplyEndEvent | { "type": "turn_diff" } & TurnDiffEvent | { "type": "get_history_entry_response" } & GetHistoryEntryResponseEvent | { "type": "mcp_list_tools_response" } & McpListToolsResponseEvent | { "type": "list_custom_prompts_response" } & ListCustomPromptsResponseEvent | { "type": "list_skills_response" } & ListSkillsResponseEvent | { "type": "list_remote_skills_response" } & ListRemoteSkillsResponseEvent | { "type": "remote_skill_downloaded" } & RemoteSkillDownloadedEvent | { "type": "skills_update_available" } | { "type": "plan_update" } & UpdatePlanArgs | { "type": "turn_aborted" } & TurnAbortedEvent | { "type": "shutdown_complete" } | { "type": "entered_review_mode" } & ReviewRequest | { "type": "exited_review_mode" } & ExitedReviewModeEvent | { "type": "raw_response_item" } & RawResponseItemEvent | { "type": "item_started" } & ItemStartedEvent | { "type": "item_completed" } & ItemCompletedEvent | { "type": "agent_message_content_delta" } & AgentMessageContentDeltaEvent | { "type": "plan_delta" } & PlanDeltaEvent | { "type": "reasoning_content_delta" } & ReasoningContentDeltaEvent | { "type": "reasoning_raw_content_delta" } & ReasoningRawContentDeltaEvent | { "type": "collab_agent_spawn_begin" } & CollabAgentSpawnBeginEvent | { "type": "collab_agent_spawn_end" } & CollabAgentSpawnEndEvent | { "type": "collab_agent_interaction_begin" } & CollabAgentInteractionBeginEvent | { "type": "collab_agent_interaction_end" } & CollabAgentInteractionEndEvent | { "type": "collab_waiting_begin" } & CollabWaitingBeginEvent | { "type": "collab_waiting_end" } & CollabWaitingEndEvent | { "type": "collab_close_begin" } & CollabCloseBeginEvent | { "type": "collab_close_end" } & CollabCloseEndEvent;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// 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 { RemoteSkillSummary } from "./RemoteSkillSummary";
|
||||
|
||||
/**
|
||||
* Response payload for `Op::ListRemoteSkills`.
|
||||
*/
|
||||
export type ListRemoteSkillsResponseEvent = { skills: Array<RemoteSkillSummary>, };
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// 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.
|
||||
|
||||
/**
|
||||
* Response payload for `Op::DownloadRemoteSkill`.
|
||||
*/
|
||||
export type RemoteSkillDownloadedEvent = { id: string, name: string, path: string, };
|
||||
|
|
@ -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 RemoteSkillSummary = { id: string, name: string, description: string, };
|
||||
|
|
@ -98,6 +98,7 @@ export type { ItemStartedEvent } from "./ItemStartedEvent";
|
|||
export type { ListConversationsParams } from "./ListConversationsParams";
|
||||
export type { ListConversationsResponse } from "./ListConversationsResponse";
|
||||
export type { ListCustomPromptsResponseEvent } from "./ListCustomPromptsResponseEvent";
|
||||
export type { ListRemoteSkillsResponseEvent } from "./ListRemoteSkillsResponseEvent";
|
||||
export type { ListSkillsResponseEvent } from "./ListSkillsResponseEvent";
|
||||
export type { LocalShellAction } from "./LocalShellAction";
|
||||
export type { LocalShellExecAction } from "./LocalShellExecAction";
|
||||
|
|
@ -140,6 +141,8 @@ export type { ReasoningItemContent } from "./ReasoningItemContent";
|
|||
export type { ReasoningItemReasoningSummary } from "./ReasoningItemReasoningSummary";
|
||||
export type { ReasoningRawContentDeltaEvent } from "./ReasoningRawContentDeltaEvent";
|
||||
export type { ReasoningSummary } from "./ReasoningSummary";
|
||||
export type { RemoteSkillDownloadedEvent } from "./RemoteSkillDownloadedEvent";
|
||||
export type { RemoteSkillSummary } from "./RemoteSkillSummary";
|
||||
export type { RemoveConversationListenerParams } from "./RemoveConversationListenerParams";
|
||||
export type { RemoveConversationSubscriptionResponse } from "./RemoveConversationSubscriptionResponse";
|
||||
export type { RequestId } from "./RequestId";
|
||||
|
|
|
|||
|
|
@ -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 RemoteSkillSummary = { id: string, name: string, description: string, };
|
||||
|
|
@ -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 SkillsRemoteReadParams = Record<string, never>;
|
||||
|
|
@ -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 { RemoteSkillSummary } from "./RemoteSkillSummary";
|
||||
|
||||
export type SkillsRemoteReadResponse = { data: Array<RemoteSkillSummary>, };
|
||||
|
|
@ -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 SkillsRemoteWriteParams = { hazelnutId: string, isPreload: boolean, };
|
||||
|
|
@ -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 SkillsRemoteWriteResponse = { id: string, name: string, path: string, };
|
||||
|
|
@ -96,6 +96,7 @@ export type { ReasoningEffortOption } from "./ReasoningEffortOption";
|
|||
export type { ReasoningSummaryPartAddedNotification } from "./ReasoningSummaryPartAddedNotification";
|
||||
export type { ReasoningSummaryTextDeltaNotification } from "./ReasoningSummaryTextDeltaNotification";
|
||||
export type { ReasoningTextDeltaNotification } from "./ReasoningTextDeltaNotification";
|
||||
export type { RemoteSkillSummary } from "./RemoteSkillSummary";
|
||||
export type { ResidencyRequirement } from "./ResidencyRequirement";
|
||||
export type { ReviewDelivery } from "./ReviewDelivery";
|
||||
export type { ReviewStartParams } from "./ReviewStartParams";
|
||||
|
|
@ -116,6 +117,10 @@ export type { SkillsConfigWriteResponse } from "./SkillsConfigWriteResponse";
|
|||
export type { SkillsListEntry } from "./SkillsListEntry";
|
||||
export type { SkillsListParams } from "./SkillsListParams";
|
||||
export type { SkillsListResponse } from "./SkillsListResponse";
|
||||
export type { SkillsRemoteReadParams } from "./SkillsRemoteReadParams";
|
||||
export type { SkillsRemoteReadResponse } from "./SkillsRemoteReadResponse";
|
||||
export type { SkillsRemoteWriteParams } from "./SkillsRemoteWriteParams";
|
||||
export type { SkillsRemoteWriteResponse } from "./SkillsRemoteWriteResponse";
|
||||
export type { TerminalInteractionNotification } from "./TerminalInteractionNotification";
|
||||
export type { TextElement } from "./TextElement";
|
||||
export type { TextPosition } from "./TextPosition";
|
||||
|
|
|
|||
|
|
@ -228,6 +228,14 @@ client_request_definitions! {
|
|||
params: v2::SkillsListParams,
|
||||
response: v2::SkillsListResponse,
|
||||
},
|
||||
SkillsRemoteRead => "skills/remote/read" {
|
||||
params: v2::SkillsRemoteReadParams,
|
||||
response: v2::SkillsRemoteReadResponse,
|
||||
},
|
||||
SkillsRemoteWrite => "skills/remote/write" {
|
||||
params: v2::SkillsRemoteWriteParams,
|
||||
response: v2::SkillsRemoteWriteResponse,
|
||||
},
|
||||
AppsList => "app/list" {
|
||||
params: v2::AppsListParams,
|
||||
response: v2::AppsListResponse,
|
||||
|
|
|
|||
|
|
@ -1554,6 +1554,44 @@ pub struct SkillsListResponse {
|
|||
pub data: Vec<SkillsListEntry>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct SkillsRemoteReadParams {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct RemoteSkillSummary {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct SkillsRemoteReadResponse {
|
||||
pub data: Vec<RemoteSkillSummary>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct SkillsRemoteWriteParams {
|
||||
pub hazelnut_id: String,
|
||||
pub is_preload: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct SkillsRemoteWriteResponse {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(rename_all = "snake_case")]
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ Example (from OpenAI's official VSCode extension):
|
|||
- `model/list` — list available models (with reasoning effort options).
|
||||
- `collaborationMode/list` — list available collaboration mode presets (experimental, no pagination).
|
||||
- `skills/list` — list skills for one or more `cwd` values (optional `forceReload`).
|
||||
- `skills/remote/read` — list public remote skills (**under development; do not call from production clients yet**).
|
||||
- `skills/remote/write` — download a public remote skill by `hazelnutId`; `isPreload=true` writes to `.codex/vendor_imports/skills` under `codex_home` (**under development; do not call from production clients yet**).
|
||||
- `app/list` — list available apps.
|
||||
- `skills/config/write` — write user-level skill config by path.
|
||||
- `mcpServer/oauth/login` — start an OAuth login for a configured MCP server; returns an `authorization_url` and later emits `mcpServer/oauthLogin/completed` once the browser flow finishes.
|
||||
|
|
|
|||
|
|
@ -97,6 +97,10 @@ use codex_app_server_protocol::SkillsConfigWriteParams;
|
|||
use codex_app_server_protocol::SkillsConfigWriteResponse;
|
||||
use codex_app_server_protocol::SkillsListParams;
|
||||
use codex_app_server_protocol::SkillsListResponse;
|
||||
use codex_app_server_protocol::SkillsRemoteReadParams;
|
||||
use codex_app_server_protocol::SkillsRemoteReadResponse;
|
||||
use codex_app_server_protocol::SkillsRemoteWriteParams;
|
||||
use codex_app_server_protocol::SkillsRemoteWriteResponse;
|
||||
use codex_app_server_protocol::Thread;
|
||||
use codex_app_server_protocol::ThreadArchiveParams;
|
||||
use codex_app_server_protocol::ThreadArchiveResponse;
|
||||
|
|
@ -176,6 +180,8 @@ use codex_core::read_head_for_summary;
|
|||
use codex_core::read_session_meta_line;
|
||||
use codex_core::rollout_date_parts;
|
||||
use codex_core::sandboxing::SandboxPermissions;
|
||||
use codex_core::skills::remote::download_remote_skill;
|
||||
use codex_core::skills::remote::list_remote_skills;
|
||||
use codex_core::state_db::get_state_db;
|
||||
use codex_core::token_data::parse_id_token;
|
||||
use codex_core::windows_sandbox::WindowsSandboxLevelExt;
|
||||
|
|
@ -464,6 +470,12 @@ impl CodexMessageProcessor {
|
|||
ClientRequest::SkillsList { request_id, params } => {
|
||||
self.skills_list(request_id, params).await;
|
||||
}
|
||||
ClientRequest::SkillsRemoteRead { request_id, params } => {
|
||||
self.skills_remote_read(request_id, params).await;
|
||||
}
|
||||
ClientRequest::SkillsRemoteWrite { request_id, params } => {
|
||||
self.skills_remote_write(request_id, params).await;
|
||||
}
|
||||
ClientRequest::AppsList { request_id, params } => {
|
||||
self.apps_list(request_id, params).await;
|
||||
}
|
||||
|
|
@ -4053,6 +4065,61 @@ impl CodexMessageProcessor {
|
|||
.await;
|
||||
}
|
||||
|
||||
async fn skills_remote_read(&self, request_id: RequestId, _params: SkillsRemoteReadParams) {
|
||||
match list_remote_skills(&self.config).await {
|
||||
Ok(skills) => {
|
||||
let data = skills
|
||||
.into_iter()
|
||||
.map(|skill| codex_app_server_protocol::RemoteSkillSummary {
|
||||
id: skill.id,
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
})
|
||||
.collect();
|
||||
self.outgoing
|
||||
.send_response(request_id, SkillsRemoteReadResponse { data })
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
self.send_internal_error(
|
||||
request_id,
|
||||
format!("failed to read remote skills: {err}"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn skills_remote_write(&self, request_id: RequestId, params: SkillsRemoteWriteParams) {
|
||||
let SkillsRemoteWriteParams {
|
||||
hazelnut_id,
|
||||
is_preload,
|
||||
} = params;
|
||||
let response = download_remote_skill(&self.config, hazelnut_id.as_str(), is_preload).await;
|
||||
|
||||
match response {
|
||||
Ok(downloaded) => {
|
||||
self.outgoing
|
||||
.send_response(
|
||||
request_id,
|
||||
SkillsRemoteWriteResponse {
|
||||
id: downloaded.id,
|
||||
name: downloaded.name,
|
||||
path: downloaded.path,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(err) => {
|
||||
self.send_internal_error(
|
||||
request_id,
|
||||
format!("failed to download remote skill: {err}"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn skills_config_write(&self, request_id: RequestId, params: SkillsConfigWriteParams) {
|
||||
let SkillsConfigWriteParams { path, enabled } = params;
|
||||
let edits = vec![ConfigEdit::SetSkillConfig { path, enabled }];
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ url = { workspace = true }
|
|||
uuid = { workspace = true, features = ["serde", "v4", "v5"] }
|
||||
which = { workspace = true }
|
||||
wildmatch = { workspace = true }
|
||||
zip = { workspace = true }
|
||||
|
||||
[features]
|
||||
deterministic_process_ids = []
|
||||
|
|
|
|||
|
|
@ -2469,6 +2469,22 @@ async fn submission_loop(sess: Arc<Session>, config: Arc<Config>, rx_sub: Receiv
|
|||
Op::ListSkills { cwds, force_reload } => {
|
||||
handlers::list_skills(&sess, sub.id.clone(), cwds, force_reload).await;
|
||||
}
|
||||
Op::ListRemoteSkills => {
|
||||
handlers::list_remote_skills(&sess, &config, sub.id.clone()).await;
|
||||
}
|
||||
Op::DownloadRemoteSkill {
|
||||
hazelnut_id,
|
||||
is_preload,
|
||||
} => {
|
||||
handlers::download_remote_skill(
|
||||
&sess,
|
||||
&config,
|
||||
sub.id.clone(),
|
||||
hazelnut_id,
|
||||
is_preload,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Op::Undo => {
|
||||
handlers::undo(&sess, sub.id.clone()).await;
|
||||
}
|
||||
|
|
@ -2535,9 +2551,12 @@ mod handlers {
|
|||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
use codex_protocol::protocol::ListCustomPromptsResponseEvent;
|
||||
use codex_protocol::protocol::ListRemoteSkillsResponseEvent;
|
||||
use codex_protocol::protocol::ListSkillsResponseEvent;
|
||||
use codex_protocol::protocol::McpServerRefreshConfig;
|
||||
use codex_protocol::protocol::Op;
|
||||
use codex_protocol::protocol::RemoteSkillDownloadedEvent;
|
||||
use codex_protocol::protocol::RemoteSkillSummary;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::SkillsListEntry;
|
||||
|
|
@ -2895,6 +2914,77 @@ mod handlers {
|
|||
sess.send_event_raw(event).await;
|
||||
}
|
||||
|
||||
pub async fn list_remote_skills(sess: &Session, config: &Arc<Config>, sub_id: String) {
|
||||
let response = crate::skills::remote::list_remote_skills(config)
|
||||
.await
|
||||
.map(|skills| {
|
||||
skills
|
||||
.into_iter()
|
||||
.map(|skill| RemoteSkillSummary {
|
||||
id: skill.id,
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
match response {
|
||||
Ok(skills) => {
|
||||
let event = Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::ListRemoteSkillsResponse(ListRemoteSkillsResponseEvent {
|
||||
skills,
|
||||
}),
|
||||
};
|
||||
sess.send_event_raw(event).await;
|
||||
}
|
||||
Err(err) => {
|
||||
let event = Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: format!("failed to list remote skills: {err}"),
|
||||
codex_error_info: Some(CodexErrorInfo::Other),
|
||||
}),
|
||||
};
|
||||
sess.send_event_raw(event).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn download_remote_skill(
|
||||
sess: &Session,
|
||||
config: &Arc<Config>,
|
||||
sub_id: String,
|
||||
hazelnut_id: String,
|
||||
is_preload: bool,
|
||||
) {
|
||||
match crate::skills::remote::download_remote_skill(config, hazelnut_id.as_str(), is_preload)
|
||||
.await
|
||||
{
|
||||
Ok(result) => {
|
||||
let event = Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::RemoteSkillDownloaded(RemoteSkillDownloadedEvent {
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
path: result.path,
|
||||
}),
|
||||
};
|
||||
sess.send_event_raw(event).await;
|
||||
}
|
||||
Err(err) => {
|
||||
let event = Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::Error(ErrorEvent {
|
||||
message: format!("failed to download remote skill {hazelnut_id}: {err}"),
|
||||
codex_error_info: Some(CodexErrorInfo::Other),
|
||||
}),
|
||||
};
|
||||
sess.send_event_raw(event).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn undo(sess: &Arc<Session>, sub_id: String) {
|
||||
let turn_context = sess.new_default_turn_with_sub_id(sub_id).await;
|
||||
sess.spawn_task(turn_context, Vec::new(), UndoTask::new())
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ pub(crate) fn should_persist_event_msg(ev: &EventMsg) -> bool {
|
|||
| EventMsg::McpStartupComplete(_)
|
||||
| EventMsg::ListCustomPromptsResponse(_)
|
||||
| EventMsg::ListSkillsResponse(_)
|
||||
| EventMsg::ListRemoteSkillsResponse(_)
|
||||
| EventMsg::RemoteSkillDownloaded(_)
|
||||
| EventMsg::PlanUpdate(_)
|
||||
| EventMsg::ShutdownComplete
|
||||
| EventMsg::ViewImageToolCall(_)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ pub mod injection;
|
|||
pub mod loader;
|
||||
pub mod manager;
|
||||
pub mod model;
|
||||
pub mod remote;
|
||||
pub mod render;
|
||||
pub mod system;
|
||||
|
||||
|
|
|
|||
314
codex-rs/core/src/skills/remote.rs
Normal file
314
codex-rs/core/src/skills/remote.rs
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::Component;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::default_client::build_reqwest_client;
|
||||
|
||||
const REMOTE_SKILLS_API_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct RemoteSkillSummary {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct RemoteSkillDownload {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub base_sediment_id: String,
|
||||
pub files: HashMap<String, RemoteSkillFileRange>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct RemoteSkillDownloadResult {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct RemoteSkillFileRange {
|
||||
pub start: u64,
|
||||
pub length: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RemoteSkillsResponse {
|
||||
hazelnuts: Vec<RemoteSkill>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RemoteSkill {
|
||||
id: String,
|
||||
name: String,
|
||||
description: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RemoteSkillsDownloadResponse {
|
||||
hazelnuts: Vec<RemoteSkillDownloadPayload>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RemoteSkillDownloadPayload {
|
||||
id: String,
|
||||
name: String,
|
||||
#[serde(rename = "base_sediment_id")]
|
||||
base_sediment_id: String,
|
||||
files: HashMap<String, RemoteSkillFileRangePayload>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct RemoteSkillFileRangePayload {
|
||||
start: u64,
|
||||
length: u64,
|
||||
}
|
||||
|
||||
pub async fn list_remote_skills(config: &Config) -> Result<Vec<RemoteSkillSummary>> {
|
||||
let base_url = config.chatgpt_base_url.trim_end_matches('/');
|
||||
let base_url = base_url.strip_suffix("/backend-api").unwrap_or(base_url);
|
||||
let url = format!("{base_url}/public-api/hazelnuts/");
|
||||
|
||||
let client = build_reqwest_client();
|
||||
let response = client
|
||||
.get(&url)
|
||||
.timeout(REMOTE_SKILLS_API_TIMEOUT)
|
||||
.query(&[("product_surface", "codex")])
|
||||
.send()
|
||||
.await
|
||||
.with_context(|| format!("Failed to send request to {url}"))?;
|
||||
|
||||
let status = response.status();
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
if !status.is_success() {
|
||||
anyhow::bail!("Request failed with status {status} from {url}: {body}");
|
||||
}
|
||||
|
||||
let parsed: RemoteSkillsResponse =
|
||||
serde_json::from_str(&body).context("Failed to parse skills response")?;
|
||||
|
||||
Ok(parsed
|
||||
.hazelnuts
|
||||
.into_iter()
|
||||
.map(|skill| RemoteSkillSummary {
|
||||
id: skill.id,
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn download_remote_skill(
|
||||
config: &Config,
|
||||
hazelnut_id: &str,
|
||||
is_preload: bool,
|
||||
) -> Result<RemoteSkillDownloadResult> {
|
||||
let hazelnut = fetch_remote_skill(config, hazelnut_id).await?;
|
||||
|
||||
let client = build_reqwest_client();
|
||||
let base_url = config.chatgpt_base_url.trim_end_matches('/');
|
||||
let base_url = base_url.strip_suffix("/backend-api").unwrap_or(base_url);
|
||||
let url = format!("{base_url}/public-api/hazelnuts/{hazelnut_id}/export");
|
||||
let response = client
|
||||
.get(&url)
|
||||
.timeout(REMOTE_SKILLS_API_TIMEOUT)
|
||||
.send()
|
||||
.await
|
||||
.with_context(|| format!("Failed to send download request to {url}"))?;
|
||||
|
||||
let status = response.status();
|
||||
let body = response.bytes().await.context("Failed to read download")?;
|
||||
if !status.is_success() {
|
||||
let body_text = String::from_utf8_lossy(&body);
|
||||
anyhow::bail!("Download failed with status {status} from {url}: {body_text}");
|
||||
}
|
||||
|
||||
if !is_zip_payload(&body) {
|
||||
anyhow::bail!("Downloaded remote skill payload is not a zip archive");
|
||||
}
|
||||
|
||||
let preferred_dir_name = if hazelnut.name.trim().is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(hazelnut.name.as_str())
|
||||
};
|
||||
let dir_name = preferred_dir_name
|
||||
.and_then(validate_dir_name_format)
|
||||
.or_else(|| validate_dir_name_format(&hazelnut.id))
|
||||
.ok_or_else(|| anyhow::anyhow!("Remote skill has no valid directory name"))?;
|
||||
let output_root = if is_preload {
|
||||
config
|
||||
.codex_home
|
||||
.join("vendor_imports")
|
||||
.join("skills")
|
||||
.join("skills")
|
||||
.join(".curated")
|
||||
} else {
|
||||
config.codex_home.join("skills").join("downloaded")
|
||||
};
|
||||
let output_dir = output_root.join(dir_name);
|
||||
tokio::fs::create_dir_all(&output_dir)
|
||||
.await
|
||||
.context("Failed to create downloaded skills directory")?;
|
||||
|
||||
let allowed_files = hazelnut.files.keys().cloned().collect::<HashSet<String>>();
|
||||
let zip_bytes = body.to_vec();
|
||||
let output_dir_clone = output_dir.clone();
|
||||
let prefix_candidates = vec![hazelnut.name.clone(), hazelnut.id.clone()];
|
||||
tokio::task::spawn_blocking(move || {
|
||||
extract_zip_to_dir(
|
||||
zip_bytes,
|
||||
&output_dir_clone,
|
||||
&allowed_files,
|
||||
&prefix_candidates,
|
||||
)
|
||||
})
|
||||
.await
|
||||
.context("Zip extraction task failed")??;
|
||||
|
||||
Ok(RemoteSkillDownloadResult {
|
||||
id: hazelnut.id,
|
||||
name: hazelnut.name,
|
||||
path: output_dir,
|
||||
})
|
||||
}
|
||||
|
||||
fn safe_join(base: &Path, name: &str) -> Result<PathBuf> {
|
||||
let path = Path::new(name);
|
||||
for component in path.components() {
|
||||
match component {
|
||||
Component::Normal(_) => {}
|
||||
_ => {
|
||||
anyhow::bail!("Invalid file path in remote skill payload: {name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(base.join(path))
|
||||
}
|
||||
|
||||
fn validate_dir_name_format(name: &str) -> Option<String> {
|
||||
let mut components = Path::new(name).components();
|
||||
match (components.next(), components.next()) {
|
||||
(Some(Component::Normal(component)), None) => {
|
||||
let value = component.to_string_lossy().to_string();
|
||||
if value.is_empty() { None } else { Some(value) }
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zip_payload(bytes: &[u8]) -> bool {
|
||||
bytes.starts_with(b"PK\x03\x04")
|
||||
|| bytes.starts_with(b"PK\x05\x06")
|
||||
|| bytes.starts_with(b"PK\x07\x08")
|
||||
}
|
||||
|
||||
fn extract_zip_to_dir(
|
||||
bytes: Vec<u8>,
|
||||
output_dir: &Path,
|
||||
allowed_files: &HashSet<String>,
|
||||
prefix_candidates: &[String],
|
||||
) -> Result<()> {
|
||||
let cursor = std::io::Cursor::new(bytes);
|
||||
let mut archive = zip::ZipArchive::new(cursor).context("Failed to open zip archive")?;
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i).context("Failed to read zip entry")?;
|
||||
if file.is_dir() {
|
||||
continue;
|
||||
}
|
||||
let raw_name = file.name().to_string();
|
||||
let normalized = normalize_zip_name(&raw_name, prefix_candidates);
|
||||
let Some(normalized) = normalized else {
|
||||
continue;
|
||||
};
|
||||
if !allowed_files.contains(&normalized) {
|
||||
continue;
|
||||
}
|
||||
let file_path = safe_join(output_dir, &normalized)?;
|
||||
if let Some(parent) = file_path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.with_context(|| format!("Failed to create parent dir for {normalized}"))?;
|
||||
}
|
||||
let mut out = std::fs::File::create(&file_path)
|
||||
.with_context(|| format!("Failed to create file {normalized}"))?;
|
||||
std::io::copy(&mut file, &mut out)
|
||||
.with_context(|| format!("Failed to write skill file {normalized}"))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn normalize_zip_name(name: &str, prefix_candidates: &[String]) -> Option<String> {
|
||||
let mut trimmed = name.trim_start_matches("./");
|
||||
for prefix in prefix_candidates {
|
||||
if prefix.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let prefix = format!("{prefix}/");
|
||||
if let Some(rest) = trimmed.strip_prefix(&prefix) {
|
||||
trimmed = rest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(trimmed.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
async fn fetch_remote_skill(config: &Config, hazelnut_id: &str) -> Result<RemoteSkillDownload> {
|
||||
let base_url = config.chatgpt_base_url.trim_end_matches('/');
|
||||
let base_url = base_url.strip_suffix("/backend-api").unwrap_or(base_url);
|
||||
let url = format!("{base_url}/public-api/hazelnuts/");
|
||||
|
||||
let client = build_reqwest_client();
|
||||
let response = client
|
||||
.get(&url)
|
||||
.timeout(REMOTE_SKILLS_API_TIMEOUT)
|
||||
.query(&[("product_surface", "codex")])
|
||||
.send()
|
||||
.await
|
||||
.with_context(|| format!("Failed to send request to {url}"))?;
|
||||
|
||||
let status = response.status();
|
||||
let body = response.text().await.unwrap_or_default();
|
||||
if !status.is_success() {
|
||||
anyhow::bail!("Request failed with status {status} from {url}: {body}");
|
||||
}
|
||||
|
||||
let parsed: RemoteSkillsDownloadResponse =
|
||||
serde_json::from_str(&body).context("Failed to parse skills response")?;
|
||||
let hazelnut = parsed
|
||||
.hazelnuts
|
||||
.into_iter()
|
||||
.find(|hazelnut| hazelnut.id == hazelnut_id)
|
||||
.ok_or_else(|| anyhow::anyhow!("Remote skill {hazelnut_id} not found"))?;
|
||||
|
||||
Ok(RemoteSkillDownload {
|
||||
id: hazelnut.id,
|
||||
name: hazelnut.name,
|
||||
base_sediment_id: hazelnut.base_sediment_id,
|
||||
files: hazelnut
|
||||
.files
|
||||
.into_iter()
|
||||
.map(|(name, range)| {
|
||||
(
|
||||
name,
|
||||
RemoteSkillFileRange {
|
||||
start: range.start,
|
||||
length: range.length,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
|
@ -773,6 +773,8 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
|||
| EventMsg::McpListToolsResponse(_)
|
||||
| EventMsg::ListCustomPromptsResponse(_)
|
||||
| EventMsg::ListSkillsResponse(_)
|
||||
| EventMsg::ListRemoteSkillsResponse(_)
|
||||
| EventMsg::RemoteSkillDownloaded(_)
|
||||
| EventMsg::RawResponseItem(_)
|
||||
| EventMsg::UserMessage(_)
|
||||
| EventMsg::EnteredReviewMode(_)
|
||||
|
|
|
|||
|
|
@ -322,6 +322,8 @@ async fn run_codex_tool_session_inner(
|
|||
| EventMsg::McpListToolsResponse(_)
|
||||
| EventMsg::ListCustomPromptsResponse(_)
|
||||
| EventMsg::ListSkillsResponse(_)
|
||||
| EventMsg::ListRemoteSkillsResponse(_)
|
||||
| EventMsg::RemoteSkillDownloaded(_)
|
||||
| EventMsg::ExecCommandBegin(_)
|
||||
| EventMsg::TerminalInteraction(_)
|
||||
| EventMsg::ExecCommandOutputDelta(_)
|
||||
|
|
|
|||
|
|
@ -269,6 +269,15 @@ pub enum Op {
|
|||
force_reload: bool,
|
||||
},
|
||||
|
||||
/// Request the list of remote skills available via ChatGPT sharing.
|
||||
ListRemoteSkills,
|
||||
|
||||
/// Download a remote skill by id into the local skills cache.
|
||||
DownloadRemoteSkill {
|
||||
hazelnut_id: String,
|
||||
is_preload: bool,
|
||||
},
|
||||
|
||||
/// Request the agent to summarize the current conversation context.
|
||||
/// The agent will use its existing context (either conversation history or previous response id)
|
||||
/// to generate a summary which will be returned as an AgentMessage event.
|
||||
|
|
@ -822,6 +831,12 @@ pub enum EventMsg {
|
|||
/// List of skills available to the agent.
|
||||
ListSkillsResponse(ListSkillsResponseEvent),
|
||||
|
||||
/// List of remote skills available to the agent.
|
||||
ListRemoteSkillsResponse(ListRemoteSkillsResponseEvent),
|
||||
|
||||
/// Remote skill downloaded to local cache.
|
||||
RemoteSkillDownloaded(RemoteSkillDownloadedEvent),
|
||||
|
||||
/// Notification that skill data may have been updated and clients may want to reload.
|
||||
SkillsUpdateAvailable,
|
||||
|
||||
|
|
@ -2127,6 +2142,27 @@ pub struct ListSkillsResponseEvent {
|
|||
pub skills: Vec<SkillsListEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct RemoteSkillSummary {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
/// Response payload for `Op::ListRemoteSkills`.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct ListRemoteSkillsResponseEvent {
|
||||
pub skills: Vec<RemoteSkillSummary>,
|
||||
}
|
||||
|
||||
/// Response payload for `Op::DownloadRemoteSkill`.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, TS)]
|
||||
pub struct RemoteSkillDownloadedEvent {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(rename_all = "snake_case")]
|
||||
|
|
|
|||
|
|
@ -3526,6 +3526,7 @@ impl ChatWidget {
|
|||
EventMsg::McpListToolsResponse(ev) => self.on_list_mcp_tools(ev),
|
||||
EventMsg::ListCustomPromptsResponse(ev) => self.on_list_custom_prompts(ev),
|
||||
EventMsg::ListSkillsResponse(ev) => self.on_list_skills(ev),
|
||||
EventMsg::ListRemoteSkillsResponse(_) | EventMsg::RemoteSkillDownloaded(_) => {}
|
||||
EventMsg::SkillsUpdateAvailable => {
|
||||
self.submit_op(Op::ListSkills {
|
||||
cwds: Vec::new(),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue