merge: integrate orchestration
# Conflicts: # crates/flow/src/builtin.rs # crates/manifest/src/profile.rs # crates/worker/src/prompt/catalog.rs # crates/worker/src/prompt/system.rs # resources/flows/coder-review.dcdl # resources/prompts/role/coder.md # resources/prompts/role/orchestrator.md # web/workspace/src/lib/workspace/console/worker-console.ui.test.ts # web/workspace/src/lib/workspace/styles/tickets.css # web/workspace/src/routes/w/[workspaceId]/tickets/+page.svelte # web/workspace/src/routes/w/[workspaceId]/tickets/+page.ts
This commit is contained in:
@@ -18,9 +18,10 @@ use crate::model::{AuthRef, ModelManifest, ReasoningControl};
|
||||
use crate::plugin::PluginConfig;
|
||||
use crate::{
|
||||
CompactionConfig, EngineManifest, FeatureConfig, FeatureFlagConfig, FileUploadLimits,
|
||||
McpConfig, McpEnvValue, McpStdioCwdPolicy, MemoryConfig, MemoryFeatureConfig, ScopeConfig,
|
||||
SessionConfig, SkillsConfig, TicketFeatureConfig, ToolOutputLimits, ToolPermissionConfig,
|
||||
ToolPermissionRule, WebConfig, WorkerFeatureConfig, WorkerManifest, WorkerMeta,
|
||||
McpConfig, McpEnvValue, McpStdioCwdPolicy, MemoryConfig, MemoryFeatureConfig,
|
||||
MergeRequestFeatureConfig, ScopeConfig, SessionConfig, SkillsConfig, TicketFeatureConfig,
|
||||
ToolOutputLimits, ToolPermissionConfig, ToolPermissionRule, WebConfig, WorkerFeatureConfig,
|
||||
WorkerManifest, WorkerMeta,
|
||||
};
|
||||
|
||||
/// Partial-form Worker manifest. Every field is optional; one or more
|
||||
@@ -97,6 +98,8 @@ pub struct FeatureConfigPartial {
|
||||
#[serde(default)]
|
||||
pub ticket: Option<TicketFeatureConfigPartial>,
|
||||
#[serde(default)]
|
||||
pub merge_request: Option<MergeRequestFeatureConfigPartial>,
|
||||
#[serde(default)]
|
||||
pub orchestration: Option<FeatureFlagConfigPartial>,
|
||||
#[serde(default)]
|
||||
pub plugins: Option<FeatureFlagConfigPartial>,
|
||||
@@ -127,6 +130,11 @@ impl FeatureConfigPartial {
|
||||
FeatureFlagConfigPartial::merge,
|
||||
),
|
||||
ticket: merge_option(self.ticket, other.ticket, TicketFeatureConfigPartial::merge),
|
||||
merge_request: merge_option(
|
||||
self.merge_request,
|
||||
other.merge_request,
|
||||
MergeRequestFeatureConfigPartial::merge,
|
||||
),
|
||||
orchestration: merge_option(
|
||||
self.orchestration,
|
||||
other.orchestration,
|
||||
@@ -216,6 +224,28 @@ impl TicketFeatureConfigPartial {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[serde(default, deny_unknown_fields)]
|
||||
pub struct MergeRequestFeatureConfigPartial {
|
||||
pub show: Option<bool>,
|
||||
pub open: Option<bool>,
|
||||
pub review: Option<bool>,
|
||||
pub readiness_check: Option<bool>,
|
||||
pub complete: Option<bool>,
|
||||
}
|
||||
|
||||
impl MergeRequestFeatureConfigPartial {
|
||||
fn merge(self, other: Self) -> Self {
|
||||
Self {
|
||||
show: other.show.or(self.show),
|
||||
open: other.open.or(self.open),
|
||||
review: other.review.or(self.review),
|
||||
readiness_check: other.readiness_check.or(self.readiness_check),
|
||||
complete: other.complete.or(self.complete),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FeatureConfigPartial> for FeatureConfig {
|
||||
fn from(value: FeatureConfigPartial) -> Self {
|
||||
Self {
|
||||
@@ -247,6 +277,10 @@ impl From<FeatureConfigPartial> for FeatureConfig {
|
||||
.ticket
|
||||
.map(TicketFeatureConfig::from)
|
||||
.unwrap_or_default(),
|
||||
merge_request: value
|
||||
.merge_request
|
||||
.map(MergeRequestFeatureConfig::from)
|
||||
.unwrap_or_default(),
|
||||
orchestration: value
|
||||
.orchestration
|
||||
.map(FeatureFlagConfig::from)
|
||||
@@ -326,6 +360,30 @@ impl From<TicketFeatureConfig> for TicketFeatureConfigPartial {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MergeRequestFeatureConfigPartial> for MergeRequestFeatureConfig {
|
||||
fn from(value: MergeRequestFeatureConfigPartial) -> Self {
|
||||
Self {
|
||||
show: value.show.unwrap_or_default(),
|
||||
open: value.open.unwrap_or_default(),
|
||||
review: value.review.unwrap_or_default(),
|
||||
readiness_check: value.readiness_check.unwrap_or_default(),
|
||||
complete: value.complete.unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MergeRequestFeatureConfig> for MergeRequestFeatureConfigPartial {
|
||||
fn from(value: MergeRequestFeatureConfig) -> Self {
|
||||
Self {
|
||||
show: Some(value.show),
|
||||
open: Some(value.open),
|
||||
review: Some(value.review),
|
||||
readiness_check: Some(value.readiness_check),
|
||||
complete: Some(value.complete),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FeatureConfig> for FeatureConfigPartial {
|
||||
fn from(value: FeatureConfig) -> Self {
|
||||
Self {
|
||||
@@ -339,6 +397,7 @@ impl From<FeatureConfig> for FeatureConfigPartial {
|
||||
objective: Some(value.objective.into()),
|
||||
manage_workdir: Some(value.manage_workdir.into()),
|
||||
ticket: Some(value.ticket.into()),
|
||||
merge_request: Some(value.merge_request.into()),
|
||||
orchestration: Some(value.orchestration.into()),
|
||||
plugins: Some(value.plugins.into()),
|
||||
}
|
||||
@@ -1880,6 +1939,7 @@ worker_max_turns = 7
|
||||
assert!(!manifest.feature.objective.enabled);
|
||||
assert!(!manifest.feature.manage_workdir.enabled);
|
||||
assert!(!manifest.feature.ticket.enabled);
|
||||
assert!(!manifest.feature.merge_request.any());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1899,6 +1959,13 @@ thread = false
|
||||
intake = false
|
||||
workflow = false
|
||||
|
||||
[feature.merge_request]
|
||||
show = true
|
||||
open = false
|
||||
review = true
|
||||
readiness_check = false
|
||||
complete = false
|
||||
|
||||
[feature.orchestration]
|
||||
enabled = false
|
||||
"#,
|
||||
@@ -1934,6 +2001,14 @@ enabled = false
|
||||
assert!(!manifest.feature.ticket.thread);
|
||||
assert!(!manifest.feature.ticket.intake);
|
||||
assert!(!manifest.feature.ticket.workflow);
|
||||
assert_eq!(
|
||||
manifest.feature.merge_request,
|
||||
MergeRequestFeatureConfig {
|
||||
show: true,
|
||||
review: true,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert!(!manifest.feature.orchestration.enabled);
|
||||
assert!(!manifest.feature.memory.enabled);
|
||||
assert!(!manifest.feature.memory.staging);
|
||||
@@ -1957,6 +2032,13 @@ thread = false
|
||||
intake = false
|
||||
workflow = false
|
||||
|
||||
[feature.merge_request]
|
||||
show = true
|
||||
open = false
|
||||
review = true
|
||||
readiness_check = false
|
||||
complete = false
|
||||
|
||||
[feature.orchestration]
|
||||
enabled = false
|
||||
"#,
|
||||
@@ -1968,6 +2050,11 @@ enabled = false
|
||||
thread = true
|
||||
workflow = true
|
||||
|
||||
[feature.merge_request]
|
||||
open = true
|
||||
review = false
|
||||
readiness_check = true
|
||||
|
||||
[feature.orchestration]
|
||||
enabled = true
|
||||
|
||||
@@ -2017,6 +2104,16 @@ enabled = true
|
||||
assert!(manifest.feature.ticket.thread);
|
||||
assert!(!manifest.feature.ticket.intake);
|
||||
assert!(manifest.feature.ticket.workflow);
|
||||
assert_eq!(
|
||||
manifest.feature.merge_request,
|
||||
MergeRequestFeatureConfig {
|
||||
show: true,
|
||||
open: true,
|
||||
review: false,
|
||||
readiness_check: true,
|
||||
complete: false,
|
||||
}
|
||||
);
|
||||
assert!(manifest.feature.orchestration.enabled);
|
||||
assert!(manifest.feature.objective.enabled);
|
||||
assert!(manifest.feature.web.enabled);
|
||||
|
||||
@@ -125,6 +125,8 @@ pub struct FeatureConfig {
|
||||
#[serde(default)]
|
||||
pub ticket: TicketFeatureConfig,
|
||||
#[serde(default)]
|
||||
pub merge_request: MergeRequestFeatureConfig,
|
||||
#[serde(default)]
|
||||
pub orchestration: FeatureFlagConfig,
|
||||
#[serde(default)]
|
||||
pub plugins: FeatureFlagConfig,
|
||||
@@ -143,6 +145,7 @@ impl Default for FeatureConfig {
|
||||
objective: FeatureFlagConfig::disabled(),
|
||||
manage_workdir: FeatureFlagConfig::disabled(),
|
||||
ticket: TicketFeatureConfig::default(),
|
||||
merge_request: MergeRequestFeatureConfig::default(),
|
||||
orchestration: FeatureFlagConfig::disabled(),
|
||||
plugins: FeatureFlagConfig::disabled(),
|
||||
}
|
||||
@@ -252,6 +255,27 @@ pub struct TicketFeatureConfig {
|
||||
pub workflow: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MergeRequestFeatureConfig {
|
||||
#[serde(default)]
|
||||
pub show: bool,
|
||||
#[serde(default)]
|
||||
pub open: bool,
|
||||
#[serde(default)]
|
||||
pub review: bool,
|
||||
#[serde(default)]
|
||||
pub readiness_check: bool,
|
||||
#[serde(default)]
|
||||
pub complete: bool,
|
||||
}
|
||||
|
||||
impl MergeRequestFeatureConfig {
|
||||
pub fn any(self) -> bool {
|
||||
self.show || self.open || self.review || self.readiness_check || self.complete
|
||||
}
|
||||
}
|
||||
|
||||
/// External Agent Skills (`SKILL.md`) ingest configuration. Skills are
|
||||
/// loaded *only* from the directories listed here — there is no
|
||||
/// implicit `$config_dir/skills/` or builtin probe. Profile and Manifest
|
||||
|
||||
@@ -919,6 +919,37 @@ fn apply_role_profile(
|
||||
_ => serde_json::json!({ "enabled": true, "authoring": true, "thread": true }),
|
||||
};
|
||||
value["feature"]["ticket"] = ticket;
|
||||
let merge_request = match slug {
|
||||
"coder" => serde_json::json!({
|
||||
"show": true,
|
||||
"open": true,
|
||||
"review": false,
|
||||
"readiness_check": false,
|
||||
"complete": false
|
||||
}),
|
||||
"reviewer" => serde_json::json!({
|
||||
"show": true,
|
||||
"open": false,
|
||||
"review": true,
|
||||
"readiness_check": false,
|
||||
"complete": false
|
||||
}),
|
||||
"orchestrator" => serde_json::json!({
|
||||
"show": true,
|
||||
"open": false,
|
||||
"review": false,
|
||||
"readiness_check": true,
|
||||
"complete": true
|
||||
}),
|
||||
_ => serde_json::json!({
|
||||
"show": false,
|
||||
"open": false,
|
||||
"review": false,
|
||||
"readiness_check": false,
|
||||
"complete": false
|
||||
}),
|
||||
};
|
||||
value["feature"]["merge_request"] = merge_request;
|
||||
}
|
||||
|
||||
fn reject_manifest_shaped_profile(value: &serde_json::Value) -> Result<(), ProfileError> {
|
||||
@@ -1448,6 +1479,14 @@ enabled = true
|
||||
authoring = false
|
||||
thread = false
|
||||
intake = false
|
||||
|
||||
[feature.merge_request]
|
||||
show = true
|
||||
open = false
|
||||
review = true
|
||||
readiness_check = false
|
||||
complete = false
|
||||
|
||||
[feature.orchestration]
|
||||
enabled = false
|
||||
"#,
|
||||
@@ -1470,6 +1509,14 @@ enabled = false
|
||||
assert!(!resolved.manifest.feature.ticket.authoring);
|
||||
assert!(!resolved.manifest.feature.ticket.thread);
|
||||
assert!(!resolved.manifest.feature.ticket.intake);
|
||||
assert_eq!(
|
||||
resolved.manifest.feature.merge_request,
|
||||
crate::MergeRequestFeatureConfig {
|
||||
show: true,
|
||||
review: true,
|
||||
..Default::default()
|
||||
}
|
||||
);
|
||||
assert!(!resolved.manifest.feature.orchestration.enabled);
|
||||
assert_eq!(
|
||||
resolved.manifest.delegation_scope.allow[0].target,
|
||||
|
||||
Reference in New Issue
Block a user