Synced from monorepo
Changes: - Gate session-lifecycle heap steady state with a dhat soak - Unbreak merge lifecycle e2e after default model → grok-4.5 - Scan home-scope rules dirs at <root>/rules - Complete text-input paste and terminal parity - Gate project roles and personas - Use canonical editing in dialogs - Use canonical editing in search bars - Reject ambiguous MCP tool IDs - Harden Git operands for plugins - Simplify queue drain API - Pass RFC 9207 iss through MCP OAuth token exchange - Show leader roster when local agents map is empty - Use canonical editing in Persona views - Remove marketplace default-skills auto-install and purge old installs - Use canonical editing in extension forms - Add canonical dashboard text editing - Use canonical editing in settings - Add /summarize as a /recap alias - Restore previous agent when exiting dashboard - Use tool_choice auto for compaction - Settings toggle for snap-prompt-to-top on send - Update default models to grok-4.5 - Source login shell once for local bash (env + alias/function snapshot) - Template hardcoded param names in server-native tool descriptions - Fix System-Reminder XML tag injection in CLAUDE.md via agents_md - Fix remote workspace-server hardcoding LSP trust (repo code execution risk) - Clear orphaned tool-call updates at turn end - Suppress task wake after cancel - Send x-grok-client-identifier on direct API tool calls - Harden dashboard peek lease transitions - Host /btw side panel in live region (minimal mode) - Bound scroll presentation latency - Highlight multi-line constructs correctly in diffs and the file viewer - Block web_fetch non-public IPs; local opt-in is explicit-host only - Seed coding_data_retention_opt_out=false for OAuth e2es in pty-harness - Follow up clipboard delivery feedback - Use canonical editing in pickers - Route TextArea through canonical editor - Persistent "watching" status row; quieter turn markers - Gate sensitive edit targets - Expose agent registry counts and gate session churn on them - Default coding data sharing to opt-out until server preference applies - Wire chat attachment ids through gateway prompts - On auth refresh failure, issue retry - Forward preview provenance and computer lifecycle state - Document independent privacy controls and scope /privacy output - Strip SamplingError Display prefix on rate-limit UI copy - Stop dumping Cloudflare HTML into Retry failed - Disable in-place prompt edit (scroll jank on enter) - Strip forced ANSI color from gh pr view JSON - Plumb bash tool description onto ToolUsageCard wire
This commit is contained in:
parent
98c3b2438a
commit
7cfcb20d2b
292 changed files with 23315 additions and 9209 deletions
|
|
@ -14,46 +14,10 @@ use crate::types::{MarketplaceEntry, MarketplaceScan};
|
|||
/// Scan a marketplace directory for plugins, reporting whether a
|
||||
/// `plugin-index.json` component catalog was loaded.
|
||||
///
|
||||
/// Tries indexed mode first, falls back to filesystem scanning.
|
||||
/// Tries indexed mode first, falls back to filesystem scanning. The component
|
||||
/// catalog is only consulted in indexed mode: its keys are defined as index
|
||||
/// names, so the filesystem fallback ignores it.
|
||||
pub fn scan_marketplace(root: &Path) -> MarketplaceScan {
|
||||
let MarketplaceScan {
|
||||
entries: mut plugins,
|
||||
catalog_loaded,
|
||||
} = scan_plugins(root);
|
||||
|
||||
// Also scan `default-skills/` as a virtual plugin if present.
|
||||
let default_skills_dir = root.join("default-skills");
|
||||
if default_skills_dir.is_dir() {
|
||||
// default-skills/ has skills at root level (each subdir is a skill),
|
||||
// not under a skills/ subdirectory. Count SKILL.md files directly.
|
||||
let skill_count = std::fs::read_dir(&default_skills_dir)
|
||||
.ok()
|
||||
.map(|rd| {
|
||||
rd.filter_map(|e| e.ok())
|
||||
.filter(|e| e.path().join("SKILL.md").exists())
|
||||
.count()
|
||||
})
|
||||
.unwrap_or(0);
|
||||
if skill_count > 0 {
|
||||
let mut entry = scan_single_plugin(&default_skills_dir, "default-skills");
|
||||
// Override skill_count since scan_single_plugin looks under skills/.
|
||||
entry.skill_count = skill_count;
|
||||
plugins.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
MarketplaceScan {
|
||||
entries: plugins,
|
||||
catalog_loaded,
|
||||
}
|
||||
}
|
||||
|
||||
/// Core plugin scanning — tries indexed mode first, falls back to filesystem.
|
||||
///
|
||||
/// The component catalog is only consulted in indexed mode: its keys are
|
||||
/// defined as index names, so the filesystem fallback ignores it.
|
||||
fn scan_plugins(root: &Path) -> MarketplaceScan {
|
||||
// Try indexed mode.
|
||||
match index::load_index(root) {
|
||||
Ok(Some(idx)) => {
|
||||
tracing::debug!(
|
||||
|
|
@ -738,34 +702,6 @@ mod tests {
|
|||
assert_eq!(scan.entries[0].skill_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_skills_virtual_plugin_has_no_components() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
write_grok_file(
|
||||
dir.path(),
|
||||
"marketplace.json",
|
||||
r#"{"name": "m", "plugins": []}"#,
|
||||
);
|
||||
write_grok_file(
|
||||
dir.path(),
|
||||
"plugin-index.json",
|
||||
r#"{
|
||||
"version": 1,
|
||||
"plugins": { "default-skills": { "components": { "skills": [ { "name": "s" } ] } } }
|
||||
}"#,
|
||||
);
|
||||
let skill_dir = dir.path().join("default-skills").join("a-skill");
|
||||
std::fs::create_dir_all(&skill_dir).unwrap();
|
||||
std::fs::write(skill_dir.join("SKILL.md"), "# A Skill").unwrap();
|
||||
|
||||
let scan = scan_marketplace(dir.path());
|
||||
assert!(scan.catalog_loaded);
|
||||
assert_eq!(scan.entries.len(), 1);
|
||||
assert_eq!(scan.entries[0].name, "default-skills");
|
||||
assert_eq!(scan.entries[0].skill_count, 1);
|
||||
assert!(scan.entries[0].components.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn root_plugin_json_preferred() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
|
|
|||
Loading…
Reference in a new issue