mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
Expose scheduled tasks in plugin details (#32272)
## What changed - Add optional `scheduledTasks` metadata to `plugin/read` responses for remote plugins, including hourly, daily, weekday, and weekly schedules. - Preserve the distinction between unavailable metadata (`null`) and a catalog response containing no scheduled tasks (`[]`). Local plugin details return `null`. - Export the corresponding Rust, JSON Schema, and TypeScript protocol types. ## Testing - Cover scheduled-task deserialization and propagation through `plugin/read`. - Verify missing and empty remote metadata remain distinct. GitOrigin-RevId: 7af223ed0a1bf6d8f054293084a73f34c6d0332d
This commit is contained in:
1 parent
bca577d69a
commit
431ad23be4
16 files changed
+589
-2
No files matched your search
+146
@@ -13414,6 +13414,15 @@
|
|||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"scheduledTasks": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/v2/ScheduledTaskSummary"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"shareUrl": {
|
"shareUrl": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
@@ -16407,6 +16416,143 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"ScheduledTaskSchedule": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/v2/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"intervalHours": {
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"hourly"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"intervalHours",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"daily"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekdays"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/v2/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekly"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"days",
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ScheduledTaskSummary": {
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"schedule": {
|
||||||
|
"$ref": "#/definitions/v2/ScheduledTaskSchedule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"key",
|
||||||
|
"name",
|
||||||
|
"prompt",
|
||||||
|
"schedule"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"ScheduledTaskWeekday": {
|
||||||
|
"enum": [
|
||||||
|
"MO",
|
||||||
|
"TU",
|
||||||
|
"WE",
|
||||||
|
"TH",
|
||||||
|
"FR",
|
||||||
|
"SA",
|
||||||
|
"SU"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"SelectedCapabilityRoot": {
|
"SelectedCapabilityRoot": {
|
||||||
"description": "A user-selected root that can expose one or more runtime capabilities.",
|
"description": "A user-selected root that can expose one or more runtime capabilities.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
+146
@@ -9818,6 +9818,15 @@
|
|||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"scheduledTasks": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskSummary"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"shareUrl": {
|
"shareUrl": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
@@ -12811,6 +12820,143 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"ScheduledTaskSchedule": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"intervalHours": {
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"hourly"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"intervalHours",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"daily"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekdays"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekly"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"days",
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ScheduledTaskSummary": {
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"schedule": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskSchedule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"key",
|
||||||
|
"name",
|
||||||
|
"prompt",
|
||||||
|
"schedule"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"ScheduledTaskWeekday": {
|
||||||
|
"enum": [
|
||||||
|
"MO",
|
||||||
|
"TU",
|
||||||
|
"WE",
|
||||||
|
"TH",
|
||||||
|
"FR",
|
||||||
|
"SA",
|
||||||
|
"SU"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"SelectedCapabilityRoot": {
|
"SelectedCapabilityRoot": {
|
||||||
"description": "A user-selected root that can expose one or more runtime capabilities.",
|
"description": "A user-selected root that can expose one or more runtime capabilities.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@@ -192,6 +192,15 @@
|
|||||||
},
|
},
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
|
"scheduledTasks": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskSummary"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
"shareUrl": {
|
"shareUrl": {
|
||||||
"type": [
|
"type": [
|
||||||
"string",
|
"string",
|
||||||
@@ -718,6 +727,143 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"ScheduledTaskSchedule": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"intervalHours": {
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0.0,
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"hourly"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"intervalHours",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "HourlyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"daily"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "DailyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekdays"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeekdaysScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskWeekday"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"enum": [
|
||||||
|
"weekly"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskScheduleType",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"days",
|
||||||
|
"time",
|
||||||
|
"type"
|
||||||
|
],
|
||||||
|
"title": "WeeklyScheduledTaskSchedule",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ScheduledTaskSummary": {
|
||||||
|
"properties": {
|
||||||
|
"key": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"schedule": {
|
||||||
|
"$ref": "#/definitions/ScheduledTaskSchedule"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"key",
|
||||||
|
"name",
|
||||||
|
"prompt",
|
||||||
|
"schedule"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"ScheduledTaskWeekday": {
|
||||||
|
"enum": [
|
||||||
|
"MO",
|
||||||
|
"TU",
|
||||||
|
"WE",
|
||||||
|
"TH",
|
||||||
|
"FR",
|
||||||
|
"SA",
|
||||||
|
"SU"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"SkillInterface": {
|
"SkillInterface": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"brandColor": {
|
"brandColor": {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type { AppSummary } from "./AppSummary";
|
|||||||
import type { AppTemplateSummary } from "./AppTemplateSummary";
|
import type { AppTemplateSummary } from "./AppTemplateSummary";
|
||||||
import type { PluginHookSummary } from "./PluginHookSummary";
|
import type { PluginHookSummary } from "./PluginHookSummary";
|
||||||
import type { PluginSummary } from "./PluginSummary";
|
import type { PluginSummary } from "./PluginSummary";
|
||||||
|
import type { ScheduledTaskSummary } from "./ScheduledTaskSummary";
|
||||||
import type { SkillSummary } from "./SkillSummary";
|
import type { SkillSummary } from "./SkillSummary";
|
||||||
|
|
||||||
export type PluginDetail = { marketplaceName: string, marketplacePath: AbsolutePathBuf | null, summary: PluginSummary, shareUrl: string | null, description: string | null, skills: Array<SkillSummary>, hooks: Array<PluginHookSummary>, apps: Array<AppSummary>, appTemplates: Array<AppTemplateSummary>, mcpServers: Array<string>, };
|
export type PluginDetail = { marketplaceName: string, marketplacePath: AbsolutePathBuf | null, summary: PluginSummary, shareUrl: string | null, description: string | null, skills: Array<SkillSummary>, hooks: Array<PluginHookSummary>, apps: Array<AppSummary>, appTemplates: Array<AppTemplateSummary>, mcpServers: Array<string>, scheduledTasks: Array<ScheduledTaskSummary> | null, };
|
||||||
@@ -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 { ScheduledTaskWeekday } from "./ScheduledTaskWeekday";
|
||||||
|
|
||||||
|
export type ScheduledTaskSchedule = { "type": "hourly", intervalHours: number, days: Array<ScheduledTaskWeekday> | null, } | { "type": "daily", time: string, } | { "type": "weekdays", time: string, } | { "type": "weekly", days: Array<ScheduledTaskWeekday>, time: string, };
|
||||||
@@ -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 { ScheduledTaskSchedule } from "./ScheduledTaskSchedule";
|
||||||
|
|
||||||
|
export type ScheduledTaskSummary = { key: string, name: string, prompt: string, schedule: ScheduledTaskSchedule, };
|
||||||
@@ -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 ScheduledTaskWeekday = "MO" | "TU" | "WE" | "TH" | "FR" | "SA" | "SU";
|
||||||
@@ -361,6 +361,9 @@ export type { ReviewTarget } from "./ReviewTarget";
|
|||||||
export type { SandboxMode } from "./SandboxMode";
|
export type { SandboxMode } from "./SandboxMode";
|
||||||
export type { SandboxPolicy } from "./SandboxPolicy";
|
export type { SandboxPolicy } from "./SandboxPolicy";
|
||||||
export type { SandboxWorkspaceWrite } from "./SandboxWorkspaceWrite";
|
export type { SandboxWorkspaceWrite } from "./SandboxWorkspaceWrite";
|
||||||
|
export type { ScheduledTaskSchedule } from "./ScheduledTaskSchedule";
|
||||||
|
export type { ScheduledTaskSummary } from "./ScheduledTaskSummary";
|
||||||
|
export type { ScheduledTaskWeekday } from "./ScheduledTaskWeekday";
|
||||||
export type { SelectedCapabilityRoot } from "./SelectedCapabilityRoot";
|
export type { SelectedCapabilityRoot } from "./SelectedCapabilityRoot";
|
||||||
export type { SendAddCreditsNudgeEmailParams } from "./SendAddCreditsNudgeEmailParams";
|
export type { SendAddCreditsNudgeEmailParams } from "./SendAddCreditsNudgeEmailParams";
|
||||||
export type { SendAddCreditsNudgeEmailResponse } from "./SendAddCreditsNudgeEmailResponse";
|
export type { SendAddCreditsNudgeEmailResponse } from "./SendAddCreditsNudgeEmailResponse";
|
||||||
|
|||||||
@@ -663,6 +663,55 @@ pub struct PluginDetail {
|
|||||||
pub apps: Vec<AppSummary>,
|
pub apps: Vec<AppSummary>,
|
||||||
pub app_templates: Vec<AppTemplateSummary>,
|
pub app_templates: Vec<AppTemplateSummary>,
|
||||||
pub mcp_servers: Vec<String>,
|
pub mcp_servers: Vec<String>,
|
||||||
|
pub scheduled_tasks: Option<Vec<ScheduledTaskSummary>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub struct ScheduledTaskSummary {
|
||||||
|
pub key: String,
|
||||||
|
pub name: String,
|
||||||
|
pub prompt: String,
|
||||||
|
pub schedule: ScheduledTaskSchedule,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
|
#[ts(tag = "type")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub enum ScheduledTaskSchedule {
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(rename_all = "camelCase")]
|
||||||
|
Hourly {
|
||||||
|
interval_hours: u32,
|
||||||
|
days: Option<Vec<ScheduledTaskWeekday>>,
|
||||||
|
},
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(rename_all = "camelCase")]
|
||||||
|
Daily { time: String },
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(rename_all = "camelCase")]
|
||||||
|
Weekdays { time: String },
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[ts(rename_all = "camelCase")]
|
||||||
|
Weekly {
|
||||||
|
days: Vec<ScheduledTaskWeekday>,
|
||||||
|
time: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
#[ts(export_to = "v2/")]
|
||||||
|
pub enum ScheduledTaskWeekday {
|
||||||
|
Mo,
|
||||||
|
Tu,
|
||||||
|
We,
|
||||||
|
Th,
|
||||||
|
Fr,
|
||||||
|
Sa,
|
||||||
|
Su,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ Example with notification opt-out:
|
|||||||
- `marketplace/upgrade` — upgrade all configured Git plugin marketplaces, or one named marketplace when `marketplaceName` is provided. Returns selected marketplace names, upgraded roots, and per-marketplace errors.
|
- `marketplace/upgrade` — upgrade all configured Git plugin marketplaces, or one named marketplace when `marketplaceName` is provided. Returns selected marketplace names, upgraded roots, and per-marketplace errors.
|
||||||
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata, nullable remote install-policy provenance in `installPolicySource` (`WORKSPACE_SETTING` or `IMPLICIT_CANONICAL_APP`), the remote marketplace `version` and locally materialized `localVersion` when available, plugin `availability` (`AVAILABLE` by default or `DISABLED_BY_ADMIN` for remote plugins blocked upstream), fail-open `marketplaceLoadErrors` entries for marketplace files that could not be parsed or loaded, and best-effort `featuredPluginIds` for the official curated marketplace. Clients can explicitly request the remote `workspace-directory`, `shared-with-me`, or `created-by-me-remote` marketplace kinds. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category (**under development; do not call from production clients yet**).
|
- `plugin/list` — list discovered plugin marketplaces and plugin state, including effective marketplace install/auth policy metadata, nullable remote install-policy provenance in `installPolicySource` (`WORKSPACE_SETTING` or `IMPLICIT_CANONICAL_APP`), the remote marketplace `version` and locally materialized `localVersion` when available, plugin `availability` (`AVAILABLE` by default or `DISABLED_BY_ADMIN` for remote plugins blocked upstream), fail-open `marketplaceLoadErrors` entries for marketplace files that could not be parsed or loaded, and best-effort `featuredPluginIds` for the official curated marketplace. Clients can explicitly request the remote `workspace-directory`, `shared-with-me`, or `created-by-me-remote` marketplace kinds. `interface.category` uses the marketplace category when present; otherwise it falls back to the plugin manifest category (**under development; do not call from production clients yet**).
|
||||||
- `plugin/installed` — list installed plugin rows plus any explicitly requested local install-suggestion plugin names, without fetching the broader remote catalog. Remote rows include nullable `installPolicySource`; local rows return `null`. Mention surfaces can use this narrower view when they need plugin mention payloads rather than plugin-page discovery data (**under development; do not call from production clients yet**).
|
- `plugin/installed` — list installed plugin rows plus any explicitly requested local install-suggestion plugin names, without fetching the broader remote catalog. Remote rows include nullable `installPolicySource`; local rows return `null`. Mention surfaces can use this narrower view when they need plugin mention payloads rather than plugin-page discovery data (**under development; do not call from production clients yet**).
|
||||||
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/hooks/apps/MCP server names. Remote plugin details expose the canonical `shareUrl` supplied by the remote catalog when available; it is `null` for local plugins or when the catalog omits it. This field is separate from `summary.shareContext`, which continues to describe user and workspace sharing state. Returned plugin skills include their current `enabled` state after local config filtering; bundled hooks are returned as lightweight declaration summaries keyed for correlation with `hooks/list`. Use `plugin/install`'s `appsNeedingAuth` to drive post-install authentication and `app/list`'s `isAccessible` to determine current connector accessibility (**under development; do not call from production clients yet**).
|
- `plugin/read` — read one plugin by `marketplacePath` plus `pluginName`, returning marketplace info, a list-style `summary`, manifest descriptions/interface metadata, and bundled skills/hooks/apps/MCP server names. Remote plugin details can include scheduled task summaries from the catalog; `scheduledTasks: null` means the metadata is unavailable, while an empty array means the catalog found no scheduled tasks. Remote plugin details expose the canonical `shareUrl` supplied by the remote catalog when available; it is `null` for local plugins or when the catalog omits it. This field is separate from `summary.shareContext`, which continues to describe user and workspace sharing state. Returned plugin skills include their current `enabled` state after local config filtering; bundled hooks are returned as lightweight declaration summaries keyed for correlation with `hooks/list`. Use `plugin/install`'s `appsNeedingAuth` to drive post-install authentication and `app/list`'s `isAccessible` to determine current connector accessibility (**under development; do not call from production clients yet**).
|
||||||
- `plugin/skill/read` — read remote plugin skill markdown on demand by `remoteMarketplaceName`, `remotePluginId`, and `skillName`. This lets clients preview uninstalled remote plugin skills without downloading the plugin bundle.
|
- `plugin/skill/read` — read remote plugin skill markdown on demand by `remoteMarketplaceName`, `remotePluginId`, and `skillName`. This lets clients preview uninstalled remote plugin skills without downloading the plugin bundle.
|
||||||
- `skills/changed` — notification emitted when watched local skill files change.
|
- `skills/changed` — notification emitted when watched local skill files change.
|
||||||
- `app/list` — list available apps.
|
- `app/list` — list available apps.
|
||||||
|
|||||||
@@ -1130,6 +1130,7 @@ impl PluginRequestProcessor {
|
|||||||
apps: app_summaries,
|
apps: app_summaries,
|
||||||
app_templates: Vec::new(),
|
app_templates: Vec::new(),
|
||||||
mcp_servers: outcome.plugin.mcp_server_names,
|
mcp_servers: outcome.plugin.mcp_server_names,
|
||||||
|
scheduled_tasks: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(remote_marketplace_name) => {
|
Err(remote_marketplace_name) => {
|
||||||
@@ -2288,6 +2289,7 @@ fn remote_plugin_detail_to_info(
|
|||||||
apps,
|
apps,
|
||||||
app_templates,
|
app_templates,
|
||||||
mcp_servers: detail.mcp_servers,
|
mcp_servers: detail.mcp_servers,
|
||||||
|
scheduled_tasks: detail.scheduled_tasks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ use codex_app_server_protocol::PluginSkillReadParams;
|
|||||||
use codex_app_server_protocol::PluginSkillReadResponse;
|
use codex_app_server_protocol::PluginSkillReadResponse;
|
||||||
use codex_app_server_protocol::PluginSource;
|
use codex_app_server_protocol::PluginSource;
|
||||||
use codex_app_server_protocol::RequestId;
|
use codex_app_server_protocol::RequestId;
|
||||||
|
use codex_app_server_protocol::ScheduledTaskSchedule;
|
||||||
|
use codex_app_server_protocol::ScheduledTaskSummary;
|
||||||
|
use codex_app_server_protocol::ScheduledTaskWeekday;
|
||||||
use codex_config::types::AuthCredentialsStoreMode;
|
use codex_config::types::AuthCredentialsStoreMode;
|
||||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
@@ -176,6 +179,27 @@ apps = true
|
|||||||
"logo_url_dark": "https://example.com/example-plugin-dark.png"
|
"logo_url_dark": "https://example.com/example-plugin-dark.png"
|
||||||
},
|
},
|
||||||
"skills": [],
|
"skills": [],
|
||||||
|
"scheduled_tasks": [
|
||||||
|
{
|
||||||
|
"key": "weekday-triage",
|
||||||
|
"name": "Weekday triage",
|
||||||
|
"prompt": "Triage the support queue.",
|
||||||
|
"schedule": {
|
||||||
|
"type": "weekdays",
|
||||||
|
"time": "08:30"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "queue-monitor",
|
||||||
|
"name": "Queue monitor",
|
||||||
|
"prompt": "Check the queue.",
|
||||||
|
"schedule": {
|
||||||
|
"type": "hourly",
|
||||||
|
"intervalHours": 2,
|
||||||
|
"days": ["MO", "WE", "FR"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"mcp_servers": [
|
"mcp_servers": [
|
||||||
{
|
{
|
||||||
"key": "example-server",
|
"key": "example-server",
|
||||||
@@ -307,6 +331,32 @@ apps = true
|
|||||||
response.plugin.mcp_servers,
|
response.plugin.mcp_servers,
|
||||||
vec!["other-server".to_string()]
|
vec!["other-server".to_string()]
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
response.plugin.scheduled_tasks,
|
||||||
|
Some(vec![
|
||||||
|
ScheduledTaskSummary {
|
||||||
|
key: "weekday-triage".to_string(),
|
||||||
|
name: "Weekday triage".to_string(),
|
||||||
|
prompt: "Triage the support queue.".to_string(),
|
||||||
|
schedule: ScheduledTaskSchedule::Weekdays {
|
||||||
|
time: "08:30".to_string(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ScheduledTaskSummary {
|
||||||
|
key: "queue-monitor".to_string(),
|
||||||
|
name: "Queue monitor".to_string(),
|
||||||
|
prompt: "Check the queue.".to_string(),
|
||||||
|
schedule: ScheduledTaskSchedule::Hourly {
|
||||||
|
interval_hours: 2,
|
||||||
|
days: Some(vec![
|
||||||
|
ScheduledTaskWeekday::Mo,
|
||||||
|
ScheduledTaskWeekday::We,
|
||||||
|
ScheduledTaskWeekday::Fr,
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
response
|
response
|
||||||
.plugin
|
.plugin
|
||||||
@@ -975,6 +1025,7 @@ enabled = true
|
|||||||
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
|
||||||
)
|
)
|
||||||
.await??;
|
.await??;
|
||||||
|
assert_eq!(response.result["plugin"]["scheduledTasks"], json!(null));
|
||||||
let response: PluginReadResponse = to_response(response)?;
|
let response: PluginReadResponse = to_response(response)?;
|
||||||
|
|
||||||
assert_eq!(response.plugin.marketplace_name, "openai-curated");
|
assert_eq!(response.plugin.marketplace_name, "openai-curated");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use codex_app_server_protocol::PluginAvailability;
|
|||||||
use codex_app_server_protocol::PluginInstallPolicy;
|
use codex_app_server_protocol::PluginInstallPolicy;
|
||||||
use codex_app_server_protocol::PluginInstallPolicySource;
|
use codex_app_server_protocol::PluginInstallPolicySource;
|
||||||
use codex_app_server_protocol::PluginInterface;
|
use codex_app_server_protocol::PluginInterface;
|
||||||
|
use codex_app_server_protocol::ScheduledTaskSummary;
|
||||||
use codex_app_server_protocol::SkillInterface;
|
use codex_app_server_protocol::SkillInterface;
|
||||||
use codex_login::CodexAuth;
|
use codex_login::CodexAuth;
|
||||||
use codex_login::default_client::build_reqwest_client;
|
use codex_login::default_client::build_reqwest_client;
|
||||||
@@ -209,6 +210,7 @@ pub struct RemotePluginDetail {
|
|||||||
pub app_ids: Vec<String>,
|
pub app_ids: Vec<String>,
|
||||||
pub app_templates: Vec<RemoteAppTemplate>,
|
pub app_templates: Vec<RemoteAppTemplate>,
|
||||||
pub mcp_servers: Vec<String>,
|
pub mcp_servers: Vec<String>,
|
||||||
|
pub scheduled_tasks: Option<Vec<ScheduledTaskSummary>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@@ -504,6 +506,7 @@ struct RemotePluginReleaseResponse {
|
|||||||
skills: Vec<RemotePluginSkillResponse>,
|
skills: Vec<RemotePluginSkillResponse>,
|
||||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
mcp_servers: Vec<RemotePluginMcpServerResponse>,
|
mcp_servers: Vec<RemotePluginMcpServerResponse>,
|
||||||
|
scheduled_tasks: Option<Vec<ScheduledTaskSummary>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
@@ -1290,6 +1293,7 @@ async fn build_remote_plugin_detail(
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
mcp_servers,
|
mcp_servers,
|
||||||
|
scheduled_tasks: plugin.release.scheduled_tasks,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,24 @@ fn unknown_installation_policy_source_maps_to_none() {
|
|||||||
assert_eq!(summary.install_policy_source, None);
|
assert_eq!(summary.install_policy_source, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scheduled_task_metadata_distinguishes_unavailable_from_empty() {
|
||||||
|
let release = serde_json::json!({
|
||||||
|
"display_name": "Example",
|
||||||
|
"description": "Example plugin",
|
||||||
|
"interface": {},
|
||||||
|
});
|
||||||
|
let without_metadata: RemotePluginReleaseResponse =
|
||||||
|
serde_json::from_value(release.clone()).expect("release should deserialize");
|
||||||
|
assert_eq!(without_metadata.scheduled_tasks, None);
|
||||||
|
|
||||||
|
let mut with_empty_metadata = release;
|
||||||
|
with_empty_metadata["scheduled_tasks"] = serde_json::json!([]);
|
||||||
|
let with_empty_metadata: RemotePluginReleaseResponse =
|
||||||
|
serde_json::from_value(with_empty_metadata).expect("release should deserialize");
|
||||||
|
assert_eq!(with_empty_metadata.scheduled_tasks, Some(Vec::new()));
|
||||||
|
}
|
||||||
|
|
||||||
fn directory_plugin(id: &str, name: &str) -> RemotePluginDirectoryItem {
|
fn directory_plugin(id: &str, name: &str) -> RemotePluginDirectoryItem {
|
||||||
RemotePluginDirectoryItem {
|
RemotePluginDirectoryItem {
|
||||||
id: id.to_string(),
|
id: id.to_string(),
|
||||||
@@ -138,6 +156,7 @@ fn directory_plugin(id: &str, name: &str) -> RemotePluginDirectoryItem {
|
|||||||
},
|
},
|
||||||
skills: Vec::new(),
|
skills: Vec::new(),
|
||||||
mcp_servers: Vec::new(),
|
mcp_servers: Vec::new(),
|
||||||
|
scheduled_tasks: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1503,6 +1503,7 @@ pub(super) fn plugins_test_detail(
|
|||||||
.collect(),
|
.collect(),
|
||||||
app_templates: Vec::new(),
|
app_templates: Vec::new(),
|
||||||
mcp_servers: mcp_servers.iter().map(|name| (*name).to_string()).collect(),
|
mcp_servers: mcp_servers.iter().map(|name| (*name).to_string()).collect(),
|
||||||
|
scheduled_tasks: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1522,6 +1523,7 @@ pub(super) fn plugins_test_remote_detail(
|
|||||||
apps: Vec::new(),
|
apps: Vec::new(),
|
||||||
app_templates: Vec::new(),
|
app_templates: Vec::new(),
|
||||||
mcp_servers: Vec::new(),
|
mcp_servers: Vec::new(),
|
||||||
|
scheduled_tasks: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -876,6 +876,7 @@ async fn plugin_detail_unmaterialized_default_uses_remote_install_path() {
|
|||||||
apps: Vec::new(),
|
apps: Vec::new(),
|
||||||
app_templates: Vec::new(),
|
app_templates: Vec::new(),
|
||||||
mcp_servers: Vec::new(),
|
mcp_servers: Vec::new(),
|
||||||
|
scheduled_tasks: None,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user