From 6012b1db73fc19a3be39f76fc24e3aee56ba0d41 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 01:07:45 +0800 Subject: [PATCH 01/16] feat(rich-content): establish r0 contracts and migrations --- src-tauri/src/commands/chat.rs | 25 +- src-tauri/src/commands/session.rs | 30 +- src-tauri/src/contracts.rs | 30 ++ src-tauri/src/db/migrations.rs | 60 +++ src-tauri/src/db/mod.rs | 2 +- src-tauri/src/db/models.rs | 6 + src-tauri/src/db/repository/artifact_repo.rs | 147 ++++++ .../src/db/repository/message_block_repo.rs | 154 +++++++ src-tauri/src/db/repository/message_repo.rs | 1 + src-tauri/src/db/repository/mod.rs | 4 + src-tauri/src/services/artifacts/mod.rs | 6 + src-tauri/src/services/artifacts/types.rs | 117 +++++ .../src/services/content/block_service.rs | 24 + src-tauri/src/services/content/mod.rs | 8 + src-tauri/src/services/content/normalizer.rs | 32 ++ src-tauri/src/services/content/types.rs | 430 ++++++++++++++++++ src-tauri/src/services/mcp/tool_loop.rs | 1 + src-tauri/src/services/mod.rs | 2 + src-tauri/tests/chat_commands_tests.rs | 1 + src-tauri/tests/llm_backend_tests.rs | 1 + src/lib/ipc/index.ts | 12 + src/lib/ipc/types.ts | 90 ++++ 22 files changed, 1176 insertions(+), 7 deletions(-) create mode 100644 src-tauri/src/db/repository/artifact_repo.rs create mode 100644 src-tauri/src/db/repository/message_block_repo.rs create mode 100644 src-tauri/src/services/artifacts/mod.rs create mode 100644 src-tauri/src/services/artifacts/types.rs create mode 100644 src-tauri/src/services/content/block_service.rs create mode 100644 src-tauri/src/services/content/mod.rs create mode 100644 src-tauri/src/services/content/normalizer.rs create mode 100644 src-tauri/src/services/content/types.rs diff --git a/src-tauri/src/commands/chat.rs b/src-tauri/src/commands/chat.rs index 0572174..9a203a0 100644 --- a/src-tauri/src/commands/chat.rs +++ b/src-tauri/src/commands/chat.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use tauri::{AppHandle, State}; use crate::db::models::Message; -use crate::db::repository::{MessageRepo, SessionRepo}; +use crate::db::repository::{MessageBlockRepo, MessageRepo, SessionRepo}; use crate::services::chat; use crate::services::llm::backend::MessageAttachment; use crate::services::llm::config::LlmConfig; @@ -292,11 +292,28 @@ pub fn get_messages( let db = state.db.lock().map_err(|e| e.to_string())?; let limit = limit.unwrap_or(50).min(200); - let messages = if let Some(ref bid) = before_id { + let mut messages = if let Some(ref bid) = before_id { MessageRepo::find_before(&db, &session_id, bid, limit) } else { MessageRepo::find_recent(&db, &session_id, limit) - }; + } + .map_err(|error| error.to_string())?; + + if state.feature_flags.rich_content_render { + let ids = messages + .iter() + .map(|message| message.id.clone()) + .collect::>(); + let blocks = + MessageBlockRepo::find_by_messages(&db, &ids).map_err(|error| error.to_string())?; + for message in &mut messages { + message.blocks = blocks + .iter() + .filter(|block| block.message_id == message.id) + .cloned() + .collect(); + } + } - messages.map_err(|e| e.to_string()) + Ok(messages) } diff --git a/src-tauri/src/commands/session.rs b/src-tauri/src/commands/session.rs index a609e6a..4463926 100644 --- a/src-tauri/src/commands/session.rs +++ b/src-tauri/src/commands/session.rs @@ -4,7 +4,10 @@ use tauri::State; use crate::config; use crate::db::models::{ExportData, ExportSession, ImportResult, MessageSearchResult, Session}; -use crate::db::repository::{MessageRepo, SessionRepo, WorkspaceRepo}; +use crate::db::repository::{ + ArtifactRepo, MessageBlockRepo, MessageRepo, SessionRepo, WorkspaceRepo, +}; +use crate::services::artifacts::RetentionState; use crate::AppState; pub const WORKSPACE_KIND_DEFAULT: &str = "default"; @@ -266,7 +269,12 @@ pub fn export_sessions_to_file( let mut export_sessions = Vec::with_capacity(session_ids.len()); for sid in session_ids { let session = SessionRepo::find_by_id(conn, sid).map_err(|e| e.to_string())?; - let messages = MessageRepo::find_recent(conn, sid, u32::MAX).map_err(|e| e.to_string())?; + let mut messages = + MessageRepo::find_recent(conn, sid, u32::MAX).map_err(|e| e.to_string())?; + for message in &mut messages { + message.blocks = + MessageBlockRepo::find_by_message(conn, &message.id).map_err(|e| e.to_string())?; + } export_sessions.push(ExportSession { session, messages }); } @@ -275,6 +283,8 @@ pub fn export_sessions_to_file( exported_at: chrono::Utc::now().to_rfc3339(), app: "MisakaX".to_string(), sessions: export_sessions, + artifact_manifest: ArtifactRepo::find_by_sessions(conn, session_ids) + .map_err(|e| e.to_string())?, }; let json = serde_json::to_string_pretty(&export_data).map_err(|e| e.to_string())?; @@ -323,6 +333,19 @@ pub fn import_sessions_from_file( imported += 1; } + for mut artifact in data.artifact_manifest { + if artifact.owner_session_id.is_empty() + || ArtifactRepo::find_by_id(conn, &artifact.artifact_id).is_ok() + { + continue; + } + // A session export intentionally contains a manifest, not binary bytes. + // Imported records stay inspectable but cannot be read until a future + // import flow transfers verified content into the artifact store. + artifact.retention_state = RetentionState::Expired; + let _ = ArtifactRepo::insert(conn, &artifact); + } + Ok(ImportResult { imported_count: imported, skipped_count: skipped, @@ -370,6 +393,9 @@ fn import_single_session(conn: &rusqlite::Connection, es: &ExportSession) -> Res for m in &es.messages { MessageRepo::import(conn, m).map_err(|e| e.to_string())?; + for block in &m.blocks { + MessageBlockRepo::insert(conn, block).map_err(|e| e.to_string())?; + } } Ok(()) } diff --git a/src-tauri/src/contracts.rs b/src-tauri/src/contracts.rs index 5dc2851..111f252 100644 --- a/src-tauri/src/contracts.rs +++ b/src-tauri/src/contracts.rs @@ -18,6 +18,24 @@ pub enum AppErrorCode { SkillQuarantineQuota, SkillPathInvalid, FilePreviewTooLarge, + ArtifactNotFound, + ArtifactAccessDenied, + ArtifactTooLarge, + ArtifactStorageQuotaExceeded, + ArtifactTypeBlocked, + ArtifactHashMismatch, + ArtifactExportCancelled, + ArtifactExportFailed, + PreviewUnsupported, + PreviewParseFailed, + PreviewResourceLimit, + PreviewCancelled, + ContentBlockInvalid, + ContentBlockUnsupported, + ChartSpecInvalid, + MapSpecInvalid, + MapTileSourceUnavailable, + MapWebglUnavailable, WorkspaceNotFound, GitNotAvailable, TerminalSessionNotFound, @@ -130,6 +148,8 @@ pub struct DomainEvent { pub struct FeatureFlags { pub workspace_terminal: bool, pub narrow_webview_capabilities: bool, + pub rich_content_write: bool, + pub rich_content_render: bool, } impl Default for FeatureFlags { @@ -137,6 +157,8 @@ impl Default for FeatureFlags { Self { workspace_terminal: true, narrow_webview_capabilities: false, + rich_content_write: false, + rich_content_render: false, } } } @@ -154,9 +176,17 @@ impl FeatureFlags { .is_some_and(|value| { matches!(value.trim().to_ascii_lowercase().as_str(), "1" | "true") }); + let rich_content_write = lookup("MISAKAX_RICH_CONTENT_WRITE").is_some_and(|value| { + matches!(value.trim().to_ascii_lowercase().as_str(), "1" | "true") + }); + let rich_content_render = lookup("MISAKAX_RICH_CONTENT_RENDER").is_some_and(|value| { + matches!(value.trim().to_ascii_lowercase().as_str(), "1" | "true") + }); Self { workspace_terminal, narrow_webview_capabilities, + rich_content_write, + rich_content_render, } } } diff --git a/src-tauri/src/db/migrations.rs b/src-tauri/src/db/migrations.rs index 8fb9d25..20352cf 100644 --- a/src-tauri/src/db/migrations.rs +++ b/src-tauri/src/db/migrations.rs @@ -70,6 +70,10 @@ pub fn run_migrations(conn: &Connection) -> Result<()> { migrate_v13(conn)?; } + if current_version < 14 { + migrate_v14(conn)?; + } + Ok(()) } @@ -636,6 +640,62 @@ fn migrate_v13(conn: &Connection) -> Result<()> { Ok(()) } +fn migrate_v14(conn: &Connection) -> Result<()> { + let tx = conn.unchecked_transaction()?; + tx.execute_batch( + " + CREATE TABLE message_blocks ( + id TEXT PRIMARY KEY, + message_id TEXT NOT NULL, + position INTEGER NOT NULL CHECK(position >= 0), + kind TEXT NOT NULL, + schema_version INTEGER NOT NULL CHECK(schema_version > 0), + payload_json TEXT NOT NULL, + status TEXT NOT NULL, + fallback_json TEXT NOT NULL DEFAULT '{}', + generation INTEGER NOT NULL DEFAULT 0, + revision INTEGER NOT NULL DEFAULT 1, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (message_id) REFERENCES messages(id) ON DELETE CASCADE, + UNIQUE(message_id, position) + ); + CREATE INDEX idx_message_blocks_message_position + ON message_blocks(message_id, position); + + CREATE TABLE artifacts ( + artifact_id TEXT PRIMARY KEY, + owner_session_id TEXT NOT NULL, + origin_message_id TEXT, + origin_kind TEXT NOT NULL, + display_name TEXT NOT NULL, + media_type TEXT NOT NULL, + byte_size INTEGER NOT NULL CHECK(byte_size >= 0), + sha256 TEXT NOT NULL, + storage_key TEXT NOT NULL, + preview_state TEXT NOT NULL, + preview_artifact_id TEXT, + retention_state TEXT NOT NULL, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + expires_at DATETIME, + FOREIGN KEY (owner_session_id) REFERENCES sessions(id) ON DELETE CASCADE, + FOREIGN KEY (origin_message_id) REFERENCES messages(id) ON DELETE SET NULL + ); + CREATE INDEX idx_artifacts_session_retention + ON artifacts(owner_session_id, retention_state, created_at DESC); + CREATE INDEX idx_artifacts_origin_message + ON artifacts(origin_message_id); + CREATE INDEX idx_artifacts_sha256 + ON artifacts(sha256); + + INSERT INTO _schema_version (version) VALUES (14); + ", + )?; + tx.commit()?; + tracing::info!("Database migrated to version 14"); + Ok(()) +} + fn inject_builtin_models_for_existing_configs(conn: &Connection) -> Result<()> { let configs = list_router_configs_for_model_injection(conn)?; for (router_config_id, provider) in configs { diff --git a/src-tauri/src/db/mod.rs b/src-tauri/src/db/mod.rs index 43321e1..3f1be80 100644 --- a/src-tauri/src/db/mod.rs +++ b/src-tauri/src/db/mod.rs @@ -26,7 +26,7 @@ pub fn init_database(db_path: &Path) -> Result { conn.execute_batch("PRAGMA foreign_keys=ON;")?; conn.execute_batch("PRAGMA busy_timeout=5000;")?; - backup_before_migration(&conn, db_path, 13)?; + backup_before_migration(&conn, db_path, 14)?; // Load sqlite-vec extension unsafe { diff --git a/src-tauri/src/db/models.rs b/src-tauri/src/db/models.rs index 5fa2241..21d5e9b 100644 --- a/src-tauri/src/db/models.rs +++ b/src-tauri/src/db/models.rs @@ -1,3 +1,5 @@ +use crate::services::artifacts::ArtifactRecord; +use crate::services::content::ContentBlock; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -53,6 +55,8 @@ pub struct Message { #[serde(default = "default_message_status")] pub status: String, pub tool_calls: Option, + #[serde(default)] + pub blocks: Vec, pub created_at: String, } @@ -196,6 +200,8 @@ pub struct ExportData { pub exported_at: String, pub app: String, pub sessions: Vec, + #[serde(default)] + pub artifact_manifest: Vec, } /// 单个会话的导出数据(含消息列表) diff --git a/src-tauri/src/db/repository/artifact_repo.rs b/src-tauri/src/db/repository/artifact_repo.rs new file mode 100644 index 0000000..6f63537 --- /dev/null +++ b/src-tauri/src/db/repository/artifact_repo.rs @@ -0,0 +1,147 @@ +use anyhow::{Context, Result}; +use rusqlite::Connection; + +use crate::services::artifacts::{ArtifactOrigin, ArtifactRecord, PreviewState, RetentionState}; + +pub struct ArtifactRepo; + +impl ArtifactRepo { + pub fn insert(conn: &Connection, record: &ArtifactRecord) -> Result<()> { + conn.execute( + "INSERT INTO artifacts ( + artifact_id, owner_session_id, origin_message_id, origin_kind, display_name, + media_type, byte_size, sha256, storage_key, preview_state, preview_artifact_id, + retention_state, created_at, expires_at + ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14)", + rusqlite::params![ + record.artifact_id, + record.owner_session_id, + record.origin_message_id, + serde_json::to_string(&record.origin_kind)?, + record.display_name, + record.media_type, + record.byte_size, + record.sha256, + record.storage_key, + serde_json::to_string(&record.preview_state)?, + record.preview_artifact_id, + serde_json::to_string(&record.retention_state)?, + record.created_at, + record.expires_at, + ], + )?; + Ok(()) + } + + pub fn find_by_id(conn: &Connection, artifact_id: &str) -> Result { + conn.query_row( + "SELECT artifact_id, owner_session_id, origin_message_id, origin_kind, display_name, + media_type, byte_size, sha256, storage_key, preview_state, preview_artifact_id, + retention_state, created_at, expires_at + FROM artifacts WHERE artifact_id = ?1", + [artifact_id], + Self::map_row, + ) + .context("ARTIFACT_NOT_FOUND") + } + + pub fn active_bytes(conn: &Connection) -> Result { + let bytes = conn.query_row( + "SELECT COALESCE(SUM(byte_size), 0) FROM artifacts WHERE retention_state = '\"active\"'", + [], + |row| row.get::<_, i64>(0), + )?; + Ok(bytes.max(0) as u64) + } + + pub fn find_by_sessions( + conn: &Connection, + session_ids: &[String], + ) -> Result> { + if session_ids.is_empty() { + return Ok(Vec::new()); + } + let placeholders = std::iter::repeat("?") + .take(session_ids.len()) + .collect::>() + .join(","); + let sql = format!( + "SELECT artifact_id, owner_session_id, origin_message_id, origin_kind, display_name, + media_type, byte_size, sha256, storage_key, preview_state, preview_artifact_id, + retention_state, created_at, expires_at + FROM artifacts WHERE owner_session_id IN ({placeholders}) ORDER BY created_at ASC" + ); + let mut statement = conn.prepare(&sql)?; + let rows = statement.query_map(rusqlite::params_from_iter(session_ids), Self::map_row)?; + rows.collect::, _>>() + .map_err(Into::into) + } + + pub fn set_retention_state( + conn: &Connection, + artifact_id: &str, + state: RetentionState, + ) -> Result<()> { + conn.execute( + "UPDATE artifacts SET retention_state = ?1 WHERE artifact_id = ?2", + rusqlite::params![serde_json::to_string(&state)?, artifact_id], + )?; + Ok(()) + } + + pub fn has_active_storage_reference( + conn: &Connection, + storage_key: &str, + exclude_artifact_id: &str, + ) -> Result { + let count = conn.query_row( + "SELECT COUNT(*) FROM artifacts + WHERE storage_key = ?1 AND artifact_id != ?2 AND retention_state = '\"active\"'", + rusqlite::params![storage_key, exclude_artifact_id], + |row| row.get::<_, i64>(0), + )?; + Ok(count > 0) + } + + fn map_row(row: &rusqlite::Row<'_>) -> rusqlite::Result { + let parse = |column: usize| -> rusqlite::Result { row.get(column) }; + let origin_kind = serde_json::from_str::(&parse(3)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 3, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + let preview_state = serde_json::from_str::(&parse(9)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 9, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + let retention_state = + serde_json::from_str::(&parse(11)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 11, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + Ok(ArtifactRecord { + artifact_id: row.get(0)?, + owner_session_id: row.get(1)?, + origin_message_id: row.get(2)?, + origin_kind, + display_name: row.get(4)?, + media_type: row.get(5)?, + byte_size: row.get::<_, i64>(6)?.max(0) as u64, + sha256: row.get(7)?, + storage_key: row.get(8)?, + preview_state, + preview_artifact_id: row.get(10)?, + retention_state, + created_at: row.get(12)?, + expires_at: row.get(13)?, + }) + } +} diff --git a/src-tauri/src/db/repository/message_block_repo.rs b/src-tauri/src/db/repository/message_block_repo.rs new file mode 100644 index 0000000..14f88f9 --- /dev/null +++ b/src-tauri/src/db/repository/message_block_repo.rs @@ -0,0 +1,154 @@ +use anyhow::Result; +use rusqlite::Connection; + +use crate::services::content::{BlockFallback, BlockStatus, ContentBlock, ContentBlockKind}; + +pub struct MessageBlockRepo; + +impl MessageBlockRepo { + pub fn insert(conn: &Connection, block: &ContentBlock) -> Result<()> { + conn.execute( + "INSERT INTO message_blocks ( + id, message_id, position, kind, schema_version, payload_json, status, + fallback_json, generation, revision, created_at, updated_at + ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)", + rusqlite::params![ + block.id, + block.message_id, + block.position, + serde_json::to_string(&block.kind)?, + block.schema_version, + serde_json::to_string(&block.payload)?, + serde_json::to_string(&block.status)?, + serde_json::to_string(&block.fallback)?, + block.generation, + block.revision, + block.created_at, + block.updated_at, + ], + )?; + Ok(()) + } + + pub fn find_by_message(conn: &Connection, message_id: &str) -> Result> { + let mut statement = conn.prepare( + "SELECT id, message_id, position, kind, schema_version, payload_json, status, + fallback_json, generation, revision, created_at, updated_at + FROM message_blocks WHERE message_id = ?1 ORDER BY position ASC, rowid ASC", + )?; + let rows = statement.query_map([message_id], Self::map_row)?; + rows.collect::, _>>() + .map_err(Into::into) + } + + pub fn find_by_messages( + conn: &Connection, + message_ids: &[String], + ) -> Result> { + if message_ids.is_empty() { + return Ok(Vec::new()); + } + let placeholders = std::iter::repeat("?") + .take(message_ids.len()) + .collect::>() + .join(","); + let sql = format!( + "SELECT id, message_id, position, kind, schema_version, payload_json, status, + fallback_json, generation, revision, created_at, updated_at + FROM message_blocks WHERE message_id IN ({placeholders}) ORDER BY message_id, position, rowid" + ); + let mut statement = conn.prepare(&sql)?; + let rows = statement.query_map(rusqlite::params_from_iter(message_ids), Self::map_row)?; + rows.collect::, _>>() + .map_err(Into::into) + } + + fn map_row(row: &rusqlite::Row<'_>) -> rusqlite::Result { + let parse = |column: usize| -> rusqlite::Result { row.get(column) }; + let kind = serde_json::from_str::(&parse(3)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 3, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + let payload = serde_json::from_str(&parse(5)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 5, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + let status = serde_json::from_str::(&parse(6)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 6, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + let fallback = serde_json::from_str::(&parse(7)?).map_err(|error| { + rusqlite::Error::FromSqlConversionFailure( + 7, + rusqlite::types::Type::Text, + Box::new(error), + ) + })?; + Ok(ContentBlock { + id: row.get(0)?, + message_id: row.get(1)?, + position: row.get(2)?, + kind, + schema_version: row.get(4)?, + payload, + status, + fallback, + generation: row.get(8)?, + revision: row.get(9)?, + created_at: row.get(10)?, + updated_at: row.get(11)?, + }) + } +} + +#[cfg(test)] +mod tests { + use rusqlite::Connection; + + use super::MessageBlockRepo; + use crate::db::repository::MessageRepo; + use crate::services::content::{BlockFallback, BlockStatus, ContentBlock, ContentBlockKind}; + + #[test] + fn round_trips_an_ordered_block_without_changing_legacy_message_content() { + let conn = Connection::open_in_memory().unwrap(); + crate::db::migrations::run_migrations(&conn).unwrap(); + conn.execute("INSERT INTO sessions (id) VALUES ('session')", []) + .unwrap(); + MessageRepo::insert_user_message(&conn, "message", "session", "legacy markdown", None) + .unwrap(); + let block = ContentBlock::new( + "message".to_string(), + 2, + ContentBlockKind::Markdown, + BlockStatus::Ready, + serde_json::json!({"text": "structured markdown"}), + BlockFallback::default(), + ); + + MessageBlockRepo::insert(&conn, &block).unwrap(); + let restored = MessageBlockRepo::find_by_message(&conn, "message").unwrap(); + + assert_eq!(restored.len(), 1); + assert_eq!(restored[0].id, block.id); + assert_eq!(restored[0].position, 2); + assert_eq!(restored[0].payload["text"], "structured markdown"); + let content: String = conn + .query_row( + "SELECT content FROM messages WHERE id = 'message'", + [], + |row| row.get(0), + ) + .unwrap(); + assert_eq!(content, "legacy markdown"); + } +} diff --git a/src-tauri/src/db/repository/message_repo.rs b/src-tauri/src/db/repository/message_repo.rs index 80347f2..49ed768 100644 --- a/src-tauri/src/db/repository/message_repo.rs +++ b/src-tauri/src/db/repository/message_repo.rs @@ -278,6 +278,7 @@ impl MessageRepo { .get::<_, Option>(8)? .unwrap_or_else(|| "complete".to_string()), tool_calls: row.get(9)?, + blocks: Vec::new(), created_at: row.get(10)?, }) } diff --git a/src-tauri/src/db/repository/mod.rs b/src-tauri/src/db/repository/mod.rs index db1906b..5b8ce82 100644 --- a/src-tauri/src/db/repository/mod.rs +++ b/src-tauri/src/db/repository/mod.rs @@ -1,5 +1,7 @@ +pub mod artifact_repo; pub mod custom_model_repo; pub mod mcp_server_repo; +pub mod message_block_repo; pub mod message_repo; pub mod message_search; pub mod router_config_repo; @@ -10,8 +12,10 @@ pub mod skill_source_repo; pub mod tool_permission_repo; pub mod workspace_repo; +pub use artifact_repo::ArtifactRepo; pub use custom_model_repo::CustomModelRepo; pub use mcp_server_repo::{McpServerRecord, McpServerRepo}; +pub use message_block_repo::MessageBlockRepo; pub use message_repo::{MessageRepo, RegenerationContext}; pub use router_config_repo::RouterConfigRepo; pub use session_repo::SessionRepo; diff --git a/src-tauri/src/services/artifacts/mod.rs b/src-tauri/src/services/artifacts/mod.rs new file mode 100644 index 0000000..22145c2 --- /dev/null +++ b/src-tauri/src/services/artifacts/mod.rs @@ -0,0 +1,6 @@ +pub mod types; + +pub use types::{ + ArtifactMetadata, ArtifactOrigin, ArtifactRecord, ContentSafetyPolicy, PreviewState, + RetentionState, +}; diff --git a/src-tauri/src/services/artifacts/types.rs b/src-tauri/src/services/artifacts/types.rs new file mode 100644 index 0000000..12e490c --- /dev/null +++ b/src-tauri/src/services/artifacts/types.rs @@ -0,0 +1,117 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ArtifactOrigin { + Model, + Agent, + Mcp, + Skill, + User, + Preview, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum PreviewState { + None, + Queued, + Ready, + Failed, + Unsupported, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum RetentionState { + Active, + Expired, + Deleted, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ArtifactRecord { + pub artifact_id: String, + pub owner_session_id: String, + pub origin_message_id: Option, + pub origin_kind: ArtifactOrigin, + pub display_name: String, + pub media_type: String, + pub byte_size: u64, + pub sha256: String, + #[serde(skip_serializing)] + pub storage_key: String, + pub preview_state: PreviewState, + pub preview_artifact_id: Option, + pub retention_state: RetentionState, + pub created_at: String, + pub expires_at: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ArtifactMetadata { + pub artifact_id: String, + pub display_name: String, + pub media_type: String, + pub byte_size: u64, + pub sha256: String, + pub origin_kind: ArtifactOrigin, + pub preview_state: PreviewState, + pub retention_state: RetentionState, + pub created_at: String, + pub expires_at: Option, +} + +impl From<&ArtifactRecord> for ArtifactMetadata { + fn from(value: &ArtifactRecord) -> Self { + Self { + artifact_id: value.artifact_id.clone(), + display_name: value.display_name.clone(), + media_type: value.media_type.clone(), + byte_size: value.byte_size, + sha256: value.sha256.clone(), + origin_kind: value.origin_kind.clone(), + preview_state: value.preview_state.clone(), + retention_state: value.retention_state.clone(), + created_at: value.created_at.clone(), + expires_at: value.expires_at.clone(), + } + } +} + +#[derive(Debug, Clone)] +pub struct ContentSafetyPolicy { + pub max_artifact_bytes: u64, + pub max_total_artifact_bytes: u64, + pub max_preview_bytes: u64, + pub max_block_payload_bytes: usize, + pub max_markdown_chars: usize, + pub max_image_pixels: u64, + pub max_chart_series: usize, + pub max_chart_points: usize, + pub max_map_features: usize, + pub max_map_properties: usize, + pub max_label_chars: usize, + pub max_text_preview_lines: usize, + pub max_text_preview_chars: usize, +} + +impl Default for ContentSafetyPolicy { + fn default() -> Self { + Self { + max_artifact_bytes: 25 * 1024 * 1024, + max_total_artifact_bytes: 500 * 1024 * 1024, + max_preview_bytes: 8 * 1024 * 1024, + max_block_payload_bytes: 512 * 1024, + max_markdown_chars: 256 * 1024, + max_image_pixels: 32_000_000, + max_chart_series: 24, + max_chart_points: 5_000, + max_map_features: 10_000, + max_map_properties: 24, + max_label_chars: 512, + max_text_preview_lines: 5_000, + max_text_preview_chars: 512 * 1024, + } + } +} diff --git a/src-tauri/src/services/content/block_service.rs b/src-tauri/src/services/content/block_service.rs new file mode 100644 index 0000000..13eb9db --- /dev/null +++ b/src-tauri/src/services/content/block_service.rs @@ -0,0 +1,24 @@ +use anyhow::Result; +use rusqlite::Connection; + +use crate::db::repository::MessageBlockRepo; +use crate::services::artifacts::ContentSafetyPolicy; + +use super::types::ContentBlock; + +pub struct MessageBlockService; + +impl MessageBlockService { + pub fn append( + conn: &Connection, + block: &ContentBlock, + policy: &ContentSafetyPolicy, + ) -> Result<()> { + block.validate(policy).map_err(anyhow::Error::msg)?; + MessageBlockRepo::insert(conn, block) + } + + pub fn list_for_message(conn: &Connection, message_id: &str) -> Result> { + MessageBlockRepo::find_by_message(conn, message_id) + } +} diff --git a/src-tauri/src/services/content/mod.rs b/src-tauri/src/services/content/mod.rs new file mode 100644 index 0000000..a24b6f5 --- /dev/null +++ b/src-tauri/src/services/content/mod.rs @@ -0,0 +1,8 @@ +pub mod block_service; +pub mod normalizer; +pub mod types; + +pub use block_service::MessageBlockService; +pub use types::{ + BlockFallback, BlockStatus, ChartSpecV1, ContentBlock, ContentBlockKind, MapSpecV1, +}; diff --git a/src-tauri/src/services/content/normalizer.rs b/src-tauri/src/services/content/normalizer.rs new file mode 100644 index 0000000..a5e45c3 --- /dev/null +++ b/src-tauri/src/services/content/normalizer.rs @@ -0,0 +1,32 @@ +//! Provider-neutral seam for R5. R0–R4 deliberately keep it free of provider code. + +use serde_json::Value; + +use super::types::{BlockFallback, BlockStatus, ContentBlock, ContentBlockKind}; + +pub fn markdown_block(message_id: String, position: i64, text: String) -> ContentBlock { + ContentBlock::new( + message_id, + position, + ContentBlockKind::Markdown, + BlockStatus::Ready, + serde_json::json!({ "text": text }), + BlockFallback::default(), + ) +} + +pub fn unsupported_block( + message_id: String, + position: i64, + payload: Value, + fallback: BlockFallback, +) -> ContentBlock { + ContentBlock::new( + message_id, + position, + ContentBlockKind::Notice, + BlockStatus::Unsupported, + payload, + fallback, + ) +} diff --git a/src-tauri/src/services/content/types.rs b/src-tauri/src/services/content/types.rs new file mode 100644 index 0000000..643345d --- /dev/null +++ b/src-tauri/src/services/content/types.rs @@ -0,0 +1,430 @@ +use std::collections::BTreeMap; + +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +use crate::services::artifacts::ContentSafetyPolicy; + +pub const CONTENT_BLOCK_SCHEMA_VERSION: u16 = 1; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ContentBlockKind { + Markdown, + Chart, + Map, + Artifact, + Image, + Notice, + #[serde(other)] + Unknown, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum BlockStatus { + Pending, + Ready, + Failed, + Unsupported, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct BlockFallback { + pub title: String, + pub message_key: String, + #[serde(default)] + pub params: BTreeMap, + #[serde(default)] + pub artifact_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ContentBlock { + pub id: String, + pub message_id: String, + pub position: i64, + pub schema_version: u16, + pub kind: ContentBlockKind, + pub status: BlockStatus, + pub payload: Value, + #[serde(default)] + pub fallback: BlockFallback, + #[serde(default)] + pub generation: u64, + #[serde(default)] + pub revision: u64, + pub created_at: String, + pub updated_at: String, +} + +impl ContentBlock { + pub fn new( + message_id: String, + position: i64, + kind: ContentBlockKind, + status: BlockStatus, + payload: Value, + fallback: BlockFallback, + ) -> Self { + let now = chrono::Utc::now().to_rfc3339(); + Self { + id: uuid::Uuid::new_v4().to_string(), + message_id, + position, + schema_version: CONTENT_BLOCK_SCHEMA_VERSION, + kind, + status, + payload, + fallback, + generation: 0, + revision: 1, + created_at: now.clone(), + updated_at: now, + } + } + + pub fn validate(&self, policy: &ContentSafetyPolicy) -> Result<(), String> { + if self.schema_version != CONTENT_BLOCK_SCHEMA_VERSION { + return Err("CONTENT_BLOCK_UNSUPPORTED".to_string()); + } + if self.message_id.trim().is_empty() || self.position < 0 { + return Err("CONTENT_BLOCK_INVALID".to_string()); + } + if serde_json::to_vec(&self.payload) + .map_err(|_| "CONTENT_BLOCK_INVALID".to_string())? + .len() + > policy.max_block_payload_bytes + { + return Err("CONTENT_BLOCK_INVALID".to_string()); + } + + match self.kind { + ContentBlockKind::Markdown => validate_markdown_payload(&self.payload, policy), + ContentBlockKind::Chart => ChartSpecV1::from_block_payload(&self.payload, policy), + ContentBlockKind::Map => MapSpecV1::from_block_payload(&self.payload, policy), + ContentBlockKind::Artifact | ContentBlockKind::Image => { + let id = self + .payload + .get("artifact_id") + .and_then(Value::as_str) + .filter(|value| uuid::Uuid::parse_str(value).is_ok()); + id.ok_or_else(|| "CONTENT_BLOCK_INVALID".to_string())?; + reject_active_content(&self.payload) + } + ContentBlockKind::Notice => { + let key = self.payload.get("message_key").and_then(Value::as_str); + if key.is_some_and(|value| !value.trim().is_empty()) { + Ok(()) + } else { + Err("CONTENT_BLOCK_INVALID".to_string()) + } + } + ContentBlockKind::Unknown => Err("CONTENT_BLOCK_UNSUPPORTED".to_string()), + } + } +} + +fn validate_markdown_payload(payload: &Value, policy: &ContentSafetyPolicy) -> Result<(), String> { + let text = payload + .get("text") + .and_then(Value::as_str) + .ok_or_else(|| "CONTENT_BLOCK_INVALID".to_string())?; + if text.len() > policy.max_markdown_chars { + return Err("CONTENT_BLOCK_INVALID".to_string()); + } + Ok(()) +} + +fn reject_active_content(payload: &Value) -> Result<(), String> { + let encoded = payload.to_string().to_ascii_lowercase(); + if encoded.contains("file:") + || encoded.contains("javascript:") + || encoded.contains(", +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChartSeries { + pub name: String, + pub values: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChartSpecV1 { + pub chart_type: ChartType, + pub title: String, + #[serde(default)] + pub summary: String, + #[serde(default)] + pub x_label: Option, + #[serde(default)] + pub y_label: Option, + #[serde(default)] + pub unit: Option, + #[serde(default)] + pub series: Vec, +} + +impl ChartSpecV1 { + pub fn validate(&self, policy: &ContentSafetyPolicy) -> Result<(), String> { + let spec = self; + if spec.title.trim().is_empty() || spec.title.len() > policy.max_label_chars { + return Err("CHART_SPEC_INVALID".to_string()); + } + if spec.series.is_empty() || spec.series.len() > policy.max_chart_series { + return Err("CHART_SPEC_INVALID".to_string()); + } + let mut points = 0usize; + for series in &spec.series { + if series.name.trim().is_empty() || series.name.len() > policy.max_label_chars { + return Err("CHART_SPEC_INVALID".to_string()); + } + points += series.values.len(); + if series.values.iter().any(|item| { + !item.y.is_finite() + || item.x.len() > policy.max_label_chars + || item + .label + .as_ref() + .is_some_and(|label| label.len() > policy.max_label_chars) + }) { + return Err("CHART_SPEC_INVALID".to_string()); + } + } + (points <= policy.max_chart_points) + .then_some(()) + .ok_or_else(|| "CHART_SPEC_INVALID".to_string()) + } + + fn from_block_payload(payload: &Value, policy: &ContentSafetyPolicy) -> Result<(), String> { + reject_active_content(payload).map_err(|_| "CHART_SPEC_INVALID".to_string())?; + let spec: Self = serde_json::from_value( + payload + .get("spec") + .cloned() + .unwrap_or_else(|| payload.clone()), + ) + .map_err(|_| "CHART_SPEC_INVALID".to_string())?; + spec.validate(policy) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GeoJsonFeatureCollection { + #[serde(rename = "type")] + pub type_name: String, + pub features: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GeoJsonFeature { + #[serde(rename = "type")] + pub type_name: String, + pub geometry: GeoJsonGeometry, + #[serde(default)] + pub properties: BTreeMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GeoJsonGeometry { + #[serde(rename = "type")] + pub type_name: String, + pub coordinates: Value, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MapMarker { + pub longitude: f64, + pub latitude: f64, + pub label: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MapInitialView { + pub longitude: f64, + pub latitude: f64, + pub zoom: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MapBounds { + pub west: f64, + pub south: f64, + pub east: f64, + pub north: f64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MapSpecV1 { + pub title: String, + #[serde(default)] + pub summary: String, + pub feature_collection: GeoJsonFeatureCollection, + #[serde(default)] + pub markers: Vec, + #[serde(default)] + pub attribution: String, + #[serde(default)] + pub initial_view: Option, + #[serde(default)] + pub bounds: Option, + #[serde(default)] + pub tile_source_id: Option, +} + +impl MapSpecV1 { + pub fn validate(&self, policy: &ContentSafetyPolicy) -> Result<(), String> { + let spec = self; + if spec.title.trim().is_empty() + || spec.feature_collection.type_name != "FeatureCollection" + || spec.feature_collection.features.len() > policy.max_map_features + || spec.markers.len() > policy.max_map_features + || spec.tile_source_id.is_some() + { + return Err("MAP_SPEC_INVALID".to_string()); + } + for marker in &spec.markers { + if !valid_coordinate(marker.longitude, marker.latitude) + || marker.label.len() > policy.max_label_chars + { + return Err("MAP_SPEC_INVALID".to_string()); + } + } + if spec.initial_view.as_ref().is_some_and(|view| { + !valid_coordinate(view.longitude, view.latitude) + || !view.zoom.is_finite() + || !(0.0..=22.0).contains(&view.zoom) + }) { + return Err("MAP_SPEC_INVALID".to_string()); + } + if spec.bounds.as_ref().is_some_and(|bounds| { + !valid_coordinate(bounds.west, bounds.south) + || !valid_coordinate(bounds.east, bounds.north) + || bounds.west > bounds.east + || bounds.south > bounds.north + }) { + return Err("MAP_SPEC_INVALID".to_string()); + } + for feature in &spec.feature_collection.features { + if feature.type_name != "Feature" + || !matches!( + feature.geometry.type_name.as_str(), + "Point" | "LineString" | "Polygon" + ) + || feature.properties.len() > policy.max_map_properties + || feature.properties.iter().any(|(key, value)| { + key.len() > policy.max_label_chars || value.len() > policy.max_label_chars + }) + || !validate_coordinates(&feature.geometry.coordinates) + { + return Err("MAP_SPEC_INVALID".to_string()); + } + } + Ok(()) + } + + fn from_block_payload(payload: &Value, policy: &ContentSafetyPolicy) -> Result<(), String> { + reject_active_content(payload).map_err(|_| "MAP_SPEC_INVALID".to_string())?; + let spec: Self = serde_json::from_value( + payload + .get("spec") + .cloned() + .unwrap_or_else(|| payload.clone()), + ) + .map_err(|_| "MAP_SPEC_INVALID".to_string())?; + spec.validate(policy) + } +} + +fn validate_coordinates(value: &Value) -> bool { + match value { + Value::Array(values) if values.len() == 2 && values.iter().all(Value::is_number) => { + let longitude = values[0].as_f64().unwrap_or(f64::NAN); + let latitude = values[1].as_f64().unwrap_or(f64::NAN); + valid_coordinate(longitude, latitude) + } + Value::Array(values) if !values.is_empty() => values.iter().all(validate_coordinates), + _ => false, + } +} + +fn valid_coordinate(longitude: f64, latitude: f64) -> bool { + longitude.is_finite() + && latitude.is_finite() + && (-180.0..=180.0).contains(&longitude) + && (-90.0..=90.0).contains(&latitude) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rejects_an_external_map_tile_and_active_payload() { + let policy = ContentSafetyPolicy::default(); + let block = ContentBlock::new( + "message".into(), + 0, + ContentBlockKind::Map, + BlockStatus::Ready, + serde_json::json!({ + "spec": { + "title": "Map", + "feature_collection": {"type": "FeatureCollection", "features": []}, + "tile_source_id": "https://example.test/{z}/{x}/{y}.png" + } + }), + BlockFallback::default(), + ); + assert_eq!(block.validate(&policy).unwrap_err(), "MAP_SPEC_INVALID"); + } + + #[test] + fn validates_safe_chart_spec() { + let policy = ContentSafetyPolicy::default(); + let block = ContentBlock::new( + "message".into(), + 0, + ContentBlockKind::Chart, + BlockStatus::Ready, + serde_json::json!({"spec": { + "chart_type": "line", "title": "Trend", + "series": [{"name": "Revenue", "values": [{"x": "Jan", "y": 12.0}]}] + }}), + BlockFallback::default(), + ); + assert!(block.validate(&policy).is_ok()); + } + + #[test] + fn maps_unknown_block_kinds_to_a_non_executing_fallback() { + let kind = serde_json::from_str::("\"future_widget\"").unwrap(); + assert_eq!(kind, ContentBlockKind::Unknown); + } +} diff --git a/src-tauri/src/services/mcp/tool_loop.rs b/src-tauri/src/services/mcp/tool_loop.rs index 24e9da4..7961f24 100644 --- a/src-tauri/src/services/mcp/tool_loop.rs +++ b/src-tauri/src/services/mcp/tool_loop.rs @@ -496,6 +496,7 @@ fn assistant_history_message(session_id: &str, content: &str) -> Message { attachments: None, status: "complete".to_string(), tool_calls: None, + blocks: Vec::new(), created_at: String::new(), } } diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index 6cb4243..c1dc5cd 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -1,4 +1,6 @@ +pub mod artifacts; pub mod chat; +pub mod content; pub mod llm; pub mod mcp; pub mod mcp_bridge; diff --git a/src-tauri/tests/chat_commands_tests.rs b/src-tauri/tests/chat_commands_tests.rs index add6bb8..f900436 100644 --- a/src-tauri/tests/chat_commands_tests.rs +++ b/src-tauri/tests/chat_commands_tests.rs @@ -134,6 +134,7 @@ mod agent_message_builders { attachments: None, status: "complete".to_string(), tool_calls: None, + blocks: Vec::new(), created_at: "now".to_string(), } } diff --git a/src-tauri/tests/llm_backend_tests.rs b/src-tauri/tests/llm_backend_tests.rs index d95f006..05c96bb 100644 --- a/src-tauri/tests/llm_backend_tests.rs +++ b/src-tauri/tests/llm_backend_tests.rs @@ -77,6 +77,7 @@ fn make_message(id: &str, role: &str, content: &str, attachments: Option<&str>) attachments: attachments.map(|s| s.to_string()), status: "complete".to_string(), tool_calls: None, + blocks: Vec::new(), created_at: "2025-01-01T00:00:00".to_string(), } } diff --git a/src/lib/ipc/index.ts b/src/lib/ipc/index.ts index 7d4f5ff..db4beac 100644 --- a/src/lib/ipc/index.ts +++ b/src/lib/ipc/index.ts @@ -31,6 +31,18 @@ export type { SystemInfo, Session, Message, + ContentBlock, + ContentBlockKind, + ContentBlockStatus, + BlockFallback, + ArtifactOrigin, + ArtifactPreviewState, + ArtifactRetentionState, + ArtifactMetadata, + ArtifactPreview, + ArtifactPreviewKind, + ArtifactRegisterRequest, + ArtifactExportOutcome, MessageRole, MessageStatus, TokenUsage, diff --git a/src/lib/ipc/types.ts b/src/lib/ipc/types.ts index a839798..ba0ff49 100644 --- a/src/lib/ipc/types.ts +++ b/src/lib/ipc/types.ts @@ -202,6 +202,89 @@ export interface Message { status: MessageStatus; created_at: string; tool_calls?: ToolCall[]; + /** Ordered R0 rich-content projection. Absent/empty preserves legacy Markdown rendering. */ + blocks?: ContentBlock[]; +} + +export type ContentBlockKind = + | "markdown" + | "chart" + | "map" + | "artifact" + | "image" + | "notice" + | "unknown"; + +export type ContentBlockStatus = "pending" | "ready" | "failed" | "unsupported"; + +export interface BlockFallback { + title: string; + message_key: string; + params?: Record; + artifact_id?: string | null; +} + +export interface ContentBlock { + id: string; + message_id: string; + position: number; + schema_version: number; + kind: ContentBlockKind; + status: ContentBlockStatus; + payload: unknown; + fallback: BlockFallback; + generation: number; + revision: number; + created_at: string; + updated_at: string; +} + +export type ArtifactOrigin = "model" | "agent" | "mcp" | "skill" | "user" | "preview"; +export type ArtifactPreviewState = "none" | "queued" | "ready" | "failed" | "unsupported"; +export type ArtifactRetentionState = "active" | "expired" | "deleted"; + +export interface ArtifactMetadata { + artifact_id: string; + display_name: string; + media_type: string; + byte_size: number; + sha256: string; + origin_kind: ArtifactOrigin; + preview_state: ArtifactPreviewState; + retention_state: ArtifactRetentionState; + created_at: string; + expires_at: string | null; +} + +export type ArtifactPreviewKind = + | "text" + | "csv" + | "pdf" + | "spreadsheet" + | "document" + | "image" + | "download_only"; + +export interface ArtifactPreview { + kind: ArtifactPreviewKind; + state: ArtifactPreviewState; + message_key: string | null; + text: string | null; + truncated: boolean; +} + +export interface ArtifactRegisterRequest { + session_id: string; + origin_message_id?: string | null; + origin_kind: ArtifactOrigin; + display_name: string; + media_type: string; + bytes_base64: string; +} + +export interface ArtifactExportOutcome { + status: "saved" | "cancelled"; + file_name: string | null; } export interface TokenUsage { @@ -513,6 +596,13 @@ export interface ExportData { exported_at: string; app: string; sessions: ExportSession[]; + artifact_manifest?: ArtifactManifestRecord[]; +} + +export interface ArtifactManifestRecord extends ArtifactMetadata { + owner_session_id: string; + origin_message_id: string | null; + preview_artifact_id: string | null; } export interface ExportSession { From 124ae9e313eb81dbdc9530b2e89f98dca7f0680e Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 01:08:45 +0800 Subject: [PATCH 02/16] docs(rich-content): record r0 CI gate --- .../06-implementation-log.md | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 docs/planning/rich-content-delivery/06-implementation-log.md diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md new file mode 100644 index 0000000..da954c3 --- /dev/null +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -0,0 +1,110 @@ +# 富内容与产物交付实施过程记录 + +> **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 +> **受众:** 所有实施者与评审者。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **状态:** R0 已提交并推送,但远程仓库未报告可查询的 CI;按阶段门禁阻塞。R1–R4 的本地改动不得推送或标记完成,直到维护者提供并通过 R0 的远程验证方式。 + +--- + +## 使用规则 + +1. 每次实际代码、依赖、迁移、CSP/capability、行为或设计文档变更后,追加一条记录;不要重写旧记录。 +2. 每条记录必须包含范围、修改文件、代码审查、本地验证、commit/push/远程 CI 状态、风险/回滚和下一步。没有执行验证时明确写“未执行”及原因。 +3. 安全决策、scope/CSP/Sandbox 策略、格式 allowlist、保留策略和 schema version 变更必须有独立 ADR 链接或本文件的决策条目。 +4. 不记录 API key、绝对用户路径、完整私有文件内容、会话内容或未脱敏命令参数。 +5. 完成某一阶段时,先满足 [AI Coding 执行说明 §7](./07-ai-coding-execution-guide.md#7-阶段完成门禁代码审查本地验证git-与远程-ci):代码审查和本地测试通过 → commit → 非强制 push → required CI 全绿(及所需 reviewer 批准)。之后才可更新 [01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md) 的状态为完成并启动下一阶段;CI 失败/不可查询时必须保持当前阶段未完成。 +6. 涉及 UI 时同步相应 `docs/design/` 文档。 + +## 阶段看板 + +| 阶段 | 状态 | 负责人 | 开始 | 完成 | 证据/备注 | +|---|---|---|---|---|---| +| R0 契约/安全基线 | 远程 CI 未配置,阻塞 | 当前实施者 | 2026-08-09 | — | `6012b1d` 已推送;迁移/双读/默认关闭 flag/安全测试已完成,本地 pass;GitHub API 未报告 check run 或 workflow run | +| R1 ArtifactService/图片/下载 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 窄 IPC + 原生保存对话框;未引入宽 URI scope;未 commit/push/CI | +| R2 文件预览 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 本地只读预览、资源上限和下载回退;未 commit/push/CI | +| R3 图表 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 受限 spec、ARIA、表格与 CSV 产物导出;未 commit/push/CI | +| R4 地图 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 仅本地 GeoJSON/no tiles;R4b 未开始;未 commit/push/CI | +| R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | +| R6 加固/发布 | 未开始 | 待分配 | — | — | 三平台/沙箱 gate;通过阶段门禁后完成 | + +## 决策记录 + +| 日期 | 决策 | 理由 | 影响 | +|---|---|---|---| +| 2026-08-08 | 采用版本化 ContentBlock + Renderer Registry,不采用 Markdown 内嵌脚本或 renderer middleware | 富内容需要独立持久化、顺序、状态、无障碍和下载生命周期;middleware 不适合作为块调度模型 | R0 schema、R3/R4 renderer、R5 adapter | +| 2026-08-08 | 所有输出文件/图片进入 Rust ArtifactService,二进制不进入 `messages.content` | 控制 I/O、哈希、配额、导出、清理和 URI 授权,避免 Base64 膨胀 | R1 DB/IPC/存储迁移 | +| 2026-08-08 | 不为本功能添加 WebView 通用 FS/HTTP/Shell 权限 | 现有 Tauri capability/CSP 已是最小权限;安全下载/预览可经 Rust 窄接口实现 | R1 URI/export、R4 网络设计 | +| 2026-08-08 | OS Sandbox 不阻塞静态富内容 MVP,但外部执行/高风险转换必须接 SandboxBroker | 内容渲染与 OS 执行隔离是不同安全问题;不能用任何一者替代另一者 | R2、R5、R6 与 Sandbox B0–B7 对齐 | +| 2026-08-08 | 地图先支持本地 GeoJSON,远程瓦片后置且必须使用 provider registry/broker | 避免模型驱动任意网络请求和 CSP 扩张 | R4a/R4b 切分 | +| 2026-08-09 | 每个 R 阶段必须在代码审查和本地测试通过后 commit/push,并等待 required CI 全绿后才能进入下一阶段 | 防止未验证阶段叠加、保留可回滚检查点,并使远程仓库成为阶段完成的权威证据 | R0–R6 执行顺序、阶段看板和交接流程 | + +## 实施记录 + +### 2026-08-08 — 规划与调研基线建立 + +- **范围:** 建立本目录的总体方案、分阶段实践、架构、功能、UI/UX、文件系统/Sandbox 调研、执行指南和资料索引。 +- **修改:** 新增 `docs/planning/rich-content-delivery/` 下的实施文档;未修改 `src/`、`src-tauri/`、`agent/`、依赖或 Tauri 配置。 +- **本地现状核验:** 阅读了聊天消息 DTO/Store/Event、Markdown renderer、图片输入附件、Rust LLM backend、SQLite message schema/repository、workspace FS commands、Tauri capability/CSP 和现有 Sandbox/开发状态文档。 +- **外部调研:** Tauri FS/permissions/CSP/asset protocol、ECharts accessibility/dataset、MapLibre CSP/worker、PDF.js、SheetJS、MDN iframe sandbox。完整链接见 [08-research-sources.md](./08-research-sources.md)。 +- **验证:** 文档路径与链接尚待本轮最终链接/文件检查;未运行构建或测试,因为未改业务代码。 +- **风险/待定:** R1 必须完成 asset protocol vs custom URI Spike;R2 必须在选 parser 前完成许可证、资源上限和恶意文件 fixture 评审;R4b 需产品确认瓦片服务与隐私规则。 +- **下一步:** 由实施者按 [07-ai-coding-execution-guide.md](./07-ai-coding-execution-guide.md) 执行 R0,先创建契约测试和迁移设计评审。 + +### 2026-08-09 — 阶段 Git/CI 门禁补充 + +- **范围:** 为后续 AI Coding 执行增加逐阶段审查、本地验证、commit/push 和远程 CI 门禁。 +- **修改:** 更新执行说明、分阶段计划与本实施记录模板;未修改产品代码、依赖、迁移或 Tauri 配置。 +- **代码审查:** 文档交叉引用与阶段顺序已核对;新增规则禁止在 CI 失败、等待、不可查询或所需 reviewer 未批准时启动下一阶段。 +- **验证:** 本目录 Markdown 本地链接检查 → pass;`git diff --check` → pass。 +- **未验证:** 未运行构建/测试,因为本次只改文档。 +- **Git:** 未提交;由当前文档维护任务的提交策略决定。 +- **远程 CI:** 不适用(仅文档编辑,尚未创建提交)。 +- **风险/回滚:** 若仓库未配置可查询的 required CI,阶段将按规则阻塞并请求维护者明确验证方式。 +- **文档同步:** [01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md)、[07-ai-coding-execution-guide.md](./07-ai-coding-execution-guide.md)。 +- **下一步:** 开始 R0 前遵循新增 §7 门禁。 + +### 2026-08-09 — R0–R4:本地实现与验证 + +- **范围:** 落地版本化 `ContentBlock`/`ArtifactRecord`、SQLite 迁移与兼容导入导出;建立应用专属 artifact store、窄 IPC/原生保存、图片与文件预览;交付受限图表和仅本地 GeoJSON 地图 renderer。 +- **修改:** `src-tauri/src/services/content/`、`services/artifacts/`、`db/migrations.rs`、repository/commands/contracts/config;`src/features/chat-content/`、消息渲染接线、IPC DTO、双语 i18n 与预览依赖;具体清单见 [R0–R4 交接](./09-r0-r4-handoff.md)。 +- **迁移/兼容性:** 新增迁移 v14 的 `message_blocks` 与 `artifacts` 表;`messages.content` 保留,旧消息不含 blocks 时继续 Markdown 渲染;导出包含 block 与 artifact manifest,导入 manifest 以 `expired` 记录保留而不假装带有二进制。 +- **安全影响:** 新块写入和读取均由默认关闭的 `MISAKAX_RICH_CONTENT_WRITE` / `MISAKAX_RICH_CONTENT_RENDER` 控制;artifact ingress 校验 session、魔数/MIME、SHA-256、原子写入、配额、路径边界、像素上限与 Office 宏标记;SVG/HTML/未知二进制不进入预览。图表只编译 allowlist spec,地图不接受 tile URL/远程资源。 +- **代码审查:** 完成 self-review,修复了受条件调用 Hook、PDF.js 6 canvas 参数、MapLibre 严格类型、Mammoth 浏览器声明、CSV 公式导出与 feature flag 双读接缝。 +- **验证:** `cargo fmt --check`、`cargo check` → pass;`cargo test --lib content` → 5 passed;`cargo test --lib artifact` → 8 passed;`npm test -- --run` → 38 files / 271 passed;`npm run build` → pass(Vite 对大懒加载 chunk 给出性能 warning)。 +- **未验证:** 未进行三平台手工预览、恶意压缩包/加密 Office 压测或远程 CI;未运行完整 Rust suite。`npm install` 报告 9 个 audit 项,未自动执行可能改变依赖树的修复。 +- **Git:** 未提交、未推送(本次请求未授权外部 Git 写入)。 +- **远程 CI:** 未执行;因此按 §7 门禁,R0–R4 不能标为正式阶段完成,也不得据此启动 R5 实现。 +- **风险/回滚:** 关闭两个 rich-content flag 即回退旧消息路径;迁移保留旧字段。删除迁移/新表前须先导出或备份。R4b 的瓦片/网络/CSP 扩张明确未实施。 +- **文档同步:** [frontend-ui-guidelines.md](../../design/frontend-ui-guidelines.md) §4.6.x.1 与本实施记录;新增 [R0–R4 交接](./09-r0-r4-handoff.md)。 +- **下一步:** 审查 diff,按阶段拆分 commit/push 并取得 required CI/reviewer 证据;之后再决定是否启动 R5。 + +### 2026-08-09 — R0:提交、推送与远程 CI 门禁 + +- **范围:** 仅提交 R0 的 ContentBlock/Artifact 契约、迁移、兼容性、默认关闭 feature flag、Repository 与契约测试;未纳入 R1–R4 的服务、renderer、依赖、UI 或交接文档改动。 +- **代码审查:** 已检查暂存差异与 `git diff --cached --check`;确认 migration v14 保留 legacy `messages.content`,未知块退回非执行 fallback,且未添加 CSP/capability/通用文件权限。未发现本阶段需修复项。 +- **验证:** `cargo fmt --check` → pass;`cargo check` → pass;`cargo test --lib content` → 5 passed / 0 failed。 +- **未验证:** R0 不涉及前端 renderer;完整 Rust suite、人工 reviewer 与三平台手工测试未执行。 +- **Git:** `6012b1db73fc19a3be39f76fc24e3aee56ba0d41`(`feat(rich-content): establish r0 contracts and migrations`)已非强制推送至 `origin/codex/rich-content-r0-r4`。 +- **远程 CI:** GitHub REST API 查询该 commit 的 `check-runs` 和 Actions runs,均返回 0。远程未配置或无法查询 required CI;按执行说明 §7.3,此阶段为“阻塞”,不能开始/推送 R1–R4。 +- **风险/回滚:** 该 R0 commit 可独立回滚;保留的 uncommitted R1–R4 本地改动不属于已通过门禁的交付。 +- **下一步:** 请仓库维护者配置或指定 R0 的 required CI 验证方式(以及需要的人工审批);验证全绿后,更新本记录并再开始 R1 的阶段审查、测试、提交和推送。 + +## 后续记录模板 + +```markdown +### YYYY-MM-DD — R?:<短标题> + +- **范围:** +- **修改:** +- **迁移/兼容性:** +- **安全影响:** +- **代码审查:** +- **验证:** `` → <结果>;手工场景 → <结果> +- **未验证:** <原因或“无”> +- **Git:** `` / ``;push → <远程/结果> +- **远程 CI:** <运行链接/required checks/状态;未通过或不可查询时说明阻塞原因> +- **风险/回滚:** +- **文档同步:** +- **下一步:** +``` From 3064b81d60ef581f11a1f0cd5763d34ad31534aa Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 01:13:43 +0800 Subject: [PATCH 03/16] ci: run phase checks on feature branches --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02ea340..8e0b126 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,9 @@ name: CI on: push: - branches: [main, master] + # Phase-gated feature branches must receive the same remote validation as + # the protected integration branches before their next stage can begin. + branches: ["**"] pull_request: branches: [main, master] From 22ac1a8ece63fa805c1ecf18da57fb490df68307 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 01:18:17 +0800 Subject: [PATCH 04/16] fix(rich-content): satisfy r0 clippy gate --- .../rich-content-delivery/06-implementation-log.md | 10 ++++++++++ src-tauri/src/db/repository/artifact_repo.rs | 3 +-- src-tauri/src/db/repository/message_block_repo.rs | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index da954c3..b3e3969 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -90,6 +90,16 @@ - **风险/回滚:** 该 R0 commit 可独立回滚;保留的 uncommitted R1–R4 本地改动不属于已通过门禁的交付。 - **下一步:** 请仓库维护者配置或指定 R0 的 required CI 验证方式(以及需要的人工审批);验证全绿后,更新本记录并再开始 R1 的阶段审查、测试、提交和推送。 +### 2026-08-09 — R0:启用分支 CI 并修复远程 Clippy + +- **范围:** 扩大现有 CI 的 push 触发范围至全部分支;修复 R0 两个 repository 的 Clippy 兼容性。未纳入 R1–R4 的服务、renderer、依赖或 UI 改动。 +- **代码审查:** CI 仍保留 `pull_request` 对 `main`/`master` 的限制,只有 `push` 触发扩展为 `"**"`,以便阶段分支得到同一套远程门禁。远程失败日志定位到 `artifact_repo.rs` 与 `message_block_repo.rs` 的 `repeat().take()`;替换为等价且不分配额外数据的 `std::iter::repeat_n()`。 +- **验证:** `cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass;`cargo test --lib content` → 5 passed / 0 failed。 +- **Git:** `3064b81`(`ci: run phase checks on feature branches`)已推送并实际触发 CI;本条记录随 R0 Clippy 修复提交推送。 +- **远程 CI:** [CI #31268907752](https://github.com/knqiufan/MisakaX/actions/runs/31268907752) 证明新分支触发已生效。前端及三平台 Terminal Runtime 均成功;Rust 作业在 Clippy 阶段因上述两处 lint 失败,Tauri Build 因依赖失败被跳过。本地修复后等待下一次完整远程运行。 +- **风险/回滚:** 该 lint 修复不改变 SQL placeholder 数量或顺序;若需要回退,可单独还原 CI 触发和两个 iterator 表达式。 +- **下一步:** 推送 R0 修复并等待所有远程 required checks 全绿,再开始 R1。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/src/db/repository/artifact_repo.rs b/src-tauri/src/db/repository/artifact_repo.rs index 6f63537..71fd8aa 100644 --- a/src-tauri/src/db/repository/artifact_repo.rs +++ b/src-tauri/src/db/repository/artifact_repo.rs @@ -61,8 +61,7 @@ impl ArtifactRepo { if session_ids.is_empty() { return Ok(Vec::new()); } - let placeholders = std::iter::repeat("?") - .take(session_ids.len()) + let placeholders = std::iter::repeat_n("?", session_ids.len()) .collect::>() .join(","); let sql = format!( diff --git a/src-tauri/src/db/repository/message_block_repo.rs b/src-tauri/src/db/repository/message_block_repo.rs index 14f88f9..afc6b9e 100644 --- a/src-tauri/src/db/repository/message_block_repo.rs +++ b/src-tauri/src/db/repository/message_block_repo.rs @@ -48,8 +48,7 @@ impl MessageBlockRepo { if message_ids.is_empty() { return Ok(Vec::new()); } - let placeholders = std::iter::repeat("?") - .take(message_ids.len()) + let placeholders = std::iter::repeat_n("?", message_ids.len()) .collect::>() .join(","); let sql = format!( From 5bf3b9696cff9ee980561031be007aa30a0a02ce Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:14:25 +0800 Subject: [PATCH 05/16] fix(rich-content): restore r0 migration fixtures --- .../06-implementation-log.md | 10 ++++++++++ src-tauri/tests/db_migrations_tests.rs | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index b3e3969..64edb8b 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -100,6 +100,16 @@ - **风险/回滚:** 该 lint 修复不改变 SQL placeholder 数量或顺序;若需要回退,可单独还原 CI 触发和两个 iterator 表达式。 - **下一步:** 推送 R0 修复并等待所有远程 required checks 全绿,再开始 R1。 +### 2026-08-09 — R0:迁移夹具回退与全量回归 + +- **范围:** 修复 R0 migration v14 对既有迁移夹具和备份测试的影响;未改变生产 schema、R1–R4 服务、renderer、依赖或 UI。 +- **代码审查:** 第二轮 CI 的 Rust 作业通过 Clippy 后,在 `test_migration_idempotent` 暴露硬编码的 v13 版本断言。进一步全量回归确认测试辅助函数在构造 v5/v10/v11/v12 fixture 时没有移除 v14 表和 schema 记录,导致重复建表、跳过前移和备份未生成。新增 `revert_v14`,在各旧版本辅助路径先删除 v14 的表、索引和版本记录;该函数仅用于测试夹具,真实迁移仍为前向单向执行。 +- **验证:** 隔离 target directory 中 `cargo test --all-features --test db_migrations_tests` → 19 passed / 0 failed;`cargo nextest run --all-features --profile ci` → 439 passed / 0 skipped;`cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass。 +- **Git:** 本条记录随 R0 migration fixture 修复提交推送。 +- **远程 CI:** [CI #31269092419](https://github.com/knqiufan/MisakaX/actions/runs/31269092419) 的前端和三平台 Terminal Runtime 成功;Rust nextest 在 v14 fixture 兼容性失败,Tauri Build 被依赖关系跳过。已完成本地全量修复,等待下一次远程运行。 +- **风险/回滚:** 只改变测试辅助代码和版本断言;可独立回退,不影响用户数据库。 +- **下一步:** 推送并等待 R0 的完整远程 CI 全绿。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/tests/db_migrations_tests.rs b/src-tauri/tests/db_migrations_tests.rs index c02d734..543f764 100644 --- a/src-tauri/tests/db_migrations_tests.rs +++ b/src-tauri/tests/db_migrations_tests.rs @@ -162,7 +162,7 @@ fn test_migration_idempotent() { row.get(0) }) .unwrap(); - assert_eq!(version, 13); + assert_eq!(version, 14); } #[test] @@ -602,6 +602,7 @@ fn test_migration_v6_injects_builtin_models_for_existing_router_configs() { fn run_migrations_to_v5(conn: &Connection) { run_migrations(conn).unwrap(); + revert_v14(conn); conn.execute_batch( "DROP TABLE skill_security_migration_items; DROP TABLE skill_security_migration; @@ -639,6 +640,7 @@ fn run_migrations_to_v5(conn: &Connection) { fn run_migrations_to_v10(conn: &Connection) { run_migrations(conn).unwrap(); + revert_v14(conn); revert_v13(conn); conn.execute_batch( "DROP TABLE skill_approvals; @@ -667,6 +669,7 @@ fn run_migrations_to_v10(conn: &Connection) { fn run_migrations_to_v11(conn: &Connection) { run_migrations(conn).unwrap(); + revert_v14(conn); revert_v13(conn); conn.execute_batch( "DROP TABLE skill_approvals; @@ -682,9 +685,23 @@ fn run_migrations_to_v11(conn: &Connection) { fn run_migrations_to_v12(conn: &Connection) { run_migrations(conn).unwrap(); + revert_v14(conn); revert_v13(conn); } +fn revert_v14(conn: &Connection) { + conn.execute_batch( + "DROP INDEX IF EXISTS idx_artifacts_sha256; + DROP INDEX IF EXISTS idx_artifacts_origin_message; + DROP INDEX IF EXISTS idx_artifacts_session_retention; + DROP TABLE IF EXISTS artifacts; + DROP INDEX IF EXISTS idx_message_blocks_message_position; + DROP TABLE IF EXISTS message_blocks; + DELETE FROM _schema_version WHERE version = 14;", + ) + .unwrap(); +} + fn revert_v13(conn: &Connection) { conn.execute_batch( "DROP TABLE skill_security_migration_items; From b1ed884373d6e2ff019143978b1b4c56aac8ce3b Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:19:16 +0800 Subject: [PATCH 06/16] fix(ci): stabilize Windows terminal startup test --- .../rich-content-delivery/06-implementation-log.md | 10 ++++++++++ src-tauri/tests/terminal_manager_tests.rs | 9 ++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index 64edb8b..e026ab1 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -110,6 +110,16 @@ - **风险/回滚:** 只改变测试辅助代码和版本断言;可独立回退,不影响用户数据库。 - **下一步:** 推送并等待 R0 的完整远程 CI 全绿。 +### 2026-08-09 — R0:Windows ConPTY CI 启动竞态修复 + +- **范围:** 仅稳定现有 Windows Terminal Runtime 集成测试的首条握手时机,以完成 R0 的远程门禁;未改变终端服务或 R0 生产功能。 +- **代码审查:** [CI #31271436559](https://github.com/knqiufan/MisakaX/actions/runs/31271436559) 中 Rust、前端、macOS 与 Ubuntu 作业均成功,Windows 的 `windows_profiles_and_long_unicode_workspace_round_trip` 未收到首条 PowerShell 命令。日志表明 ConPTY 已启动但冷启动 PowerShell 尚未就绪。测试辅助函数只在 Windows 将既有 300ms 等待提升到 1 秒;命令、断言和超时覆盖均未放宽。 +- **验证:** `cargo test --all-features --test terminal_manager_tests -- --nocapture` → 10 passed / 0 failed;`cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass。 +- **Git:** 本条记录随 CI 竞态修复提交推送。 +- **远程 CI:** 上述运行的 Windows 作业失败使 Tauri Build 跳过;本地已复现该测试集通过,等待下一次远程全矩阵验证。 +- **风险/回滚:** 只增加 Windows 测试初始化等待 700ms;不改变运行时代码、用户终端行为或安全边界。 +- **下一步:** 推送并等待 R0 全部远程检查通过。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/tests/terminal_manager_tests.rs b/src-tauri/tests/terminal_manager_tests.rs index 408a8cd..7a3122d 100644 --- a/src-tauri/tests/terminal_manager_tests.rs +++ b/src-tauri/tests/terminal_manager_tests.rs @@ -108,7 +108,14 @@ fn spawn_profile( }) .expect("PTY should spawn"); // A real xterm replies only after parsing ConPTY's initial DSR request. - std::thread::sleep(Duration::from_millis(300)); + // Windows PowerShell can still be initializing on a cold CI runner after + // the usual interactive delay, so leave enough time before the first + // handshake and command are written to the PTY. + std::thread::sleep(Duration::from_millis(if cfg!(windows) { + 1_000 + } else { + 300 + })); state } From ab7f1ee5304c7f092f246ea1fe8a3c4af002447b Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:37:08 +0800 Subject: [PATCH 07/16] feat(rich-content): complete r1 artifact delivery --- .../06-implementation-log.md | 17 +- src-tauri/src/commands/artifacts.rs | 161 +++++ src-tauri/src/commands/mod.rs | 1 + src-tauri/src/commands/session.rs | 10 +- src-tauri/src/config.rs | 7 + src-tauri/src/lib.rs | 8 + src-tauri/src/services/artifacts/mod.rs | 4 + src-tauri/src/services/artifacts/preview.rs | 111 ++++ src-tauri/src/services/artifacts/service.rs | 622 ++++++++++++++++++ src/lib/ipc/artifacts.ts | 27 + src/lib/ipc/index.ts | 1 + 11 files changed, 965 insertions(+), 4 deletions(-) create mode 100644 src-tauri/src/commands/artifacts.rs create mode 100644 src-tauri/src/services/artifacts/preview.rs create mode 100644 src-tauri/src/services/artifacts/service.rs create mode 100644 src/lib/ipc/artifacts.ts diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index e026ab1..c37cc1f 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0 已提交并推送,但远程仓库未报告可查询的 CI;按阶段门禁阻塞。R1–R4 的本地改动不得推送或标记完成,直到维护者提供并通过 R0 的远程验证方式。 +> **状态:** R0 已通过远程全量 CI。R1 ArtifactService 后端交付已完成本地验证,待提交、推送与远程 CI;R2–R4 仍未开始阶段提交。 --- @@ -20,8 +20,8 @@ | 阶段 | 状态 | 负责人 | 开始 | 完成 | 证据/备注 | |---|---|---|---|---|---| -| R0 契约/安全基线 | 远程 CI 未配置,阻塞 | 当前实施者 | 2026-08-09 | — | `6012b1d` 已推送;迁移/双读/默认关闭 flag/安全测试已完成,本地 pass;GitHub API 未报告 check run 或 workflow run | -| R1 ArtifactService/图片/下载 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 窄 IPC + 原生保存对话框;未引入宽 URI scope;未 commit/push/CI | +| R0 契约/安全基线 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `b1ed884`;[CI #31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 的 8 项检查全绿 | +| R1 ArtifactService/图片/下载 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限 ArtifactService、窄 IPC、原生保存与会话过期清理;待 commit/push/CI | | R2 文件预览 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 本地只读预览、资源上限和下载回退;未 commit/push/CI | | R3 图表 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 受限 spec、ARIA、表格与 CSV 产物导出;未 commit/push/CI | | R4 地图 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 仅本地 GeoJSON/no tiles;R4b 未开始;未 commit/push/CI | @@ -120,6 +120,17 @@ - **风险/回滚:** 只增加 Windows 测试初始化等待 700ms;不改变运行时代码、用户终端行为或安全边界。 - **下一步:** 推送并等待 R0 全部远程检查通过。 +### 2026-08-09 — R1:ArtifactService 后端与窄 IPC + +- **范围:** 提供应用私有 content-addressed artifact store、magic/MIME/尺寸/配额校验、原子写入、会话归属、过期清理、预览元数据、原生保存对话框与窄 Tauri IPC。重型预览 renderer、图表和地图仍留待 R2–R4。 +- **代码审查:** Artifact 路径只由 Rust 从 application data 目录解析;写入在 session 存在性校验后才执行;导出使用原生 dialog 并验证写出哈希;未添加 WebView FS/HTTP/Shell permission 或 URL/path 入口。会话删除前过期所属 artifact,保留数据库审计记录。 +- **验证:** `cargo fmt --check` → pass;`cargo check` → pass;`cargo test --lib artifact` → 7 passed / 0 failed。 +- **未验证:** R1 不接入重型前端 renderer;图像放大/通用文件 preview 将由 R2 覆盖。 +- **Git:** 待提交(仅 R1 后端及 IPC 文件)。 +- **远程 CI:** 待当前 R1 提交推送后运行。 +- **风险/回滚:** 关闭 rich-content feature flags 可保持旧消息路径;删除 artifact 数据前会先将记录标为 expired,并只删除无 active 引用的字节文件。 +- **下一步:** 提交、推送并等待远程 CI 全绿后,开始 R2。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/src/commands/artifacts.rs b/src-tauri/src/commands/artifacts.rs new file mode 100644 index 0000000..de19aab --- /dev/null +++ b/src-tauri/src/commands/artifacts.rs @@ -0,0 +1,161 @@ +use serde::Deserialize; +use tauri::{AppHandle, State}; +use tauri_plugin_dialog::DialogExt; + +use crate::config; +use crate::db::repository::MessageBlockRepo; +use crate::services::artifacts::{ + ArtifactMetadata, ArtifactOrigin, ArtifactPreview, ArtifactService, ContentSafetyPolicy, + ExportOutcome, +}; +use crate::services::content::{ContentBlock, MessageBlockService}; +use crate::AppState; + +#[derive(Debug, Deserialize)] +pub struct ArtifactRegisterRequest { + pub session_id: String, + pub origin_message_id: Option, + pub origin_kind: ArtifactOrigin, + pub display_name: String, + pub media_type: String, + /// Transport-only ingress. It is decoded immediately and never persisted in + /// SQLite or returned by metadata commands. + pub bytes_base64: String, +} + +fn service() -> Result { + ArtifactService::new( + config::artifacts_dir().map_err(|error| error.to_string())?, + ContentSafetyPolicy::default(), + ) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn artifact_register( + state: State<'_, AppState>, + request: ArtifactRegisterRequest, +) -> Result { + if !state.feature_flags.rich_content_write { + return Err("CONTENT_BLOCK_UNSUPPORTED".to_string()); + } + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .register_base64( + &conn, + request.session_id, + request.origin_message_id, + request.origin_kind, + request.display_name, + request.media_type, + &request.bytes_base64, + ) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn artifact_get_metadata( + state: State<'_, AppState>, + session_id: String, + artifact_id: String, +) -> Result { + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .metadata(&conn, &session_id, &artifact_id) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn artifact_get_preview( + state: State<'_, AppState>, + session_id: String, + artifact_id: String, +) -> Result { + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .preview(&conn, &session_id, &artifact_id) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn artifact_read_preview_base64( + state: State<'_, AppState>, + session_id: String, + artifact_id: String, +) -> Result { + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .read_preview_base64(&conn, &session_id, &artifact_id) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub async fn artifact_export( + app: AppHandle, + state: State<'_, AppState>, + session_id: String, + artifact_id: String, +) -> Result { + let metadata = { + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .metadata(&conn, &session_id, &artifact_id) + .map_err(|error| error.to_string())? + }; + let app_for_dialog = app.clone(); + let target = tauri::async_runtime::spawn_blocking(move || { + app_for_dialog + .dialog() + .file() + .set_title("Save artifact") + .set_file_name(metadata.display_name) + .blocking_save_file() + .and_then(|path| path.into_path().ok()) + }) + .await + .map_err(|error| error.to_string())?; + let Some(target) = target else { + return Ok(ExportOutcome { + status: "cancelled".to_string(), + file_name: None, + }); + }; + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .export_to_path(&conn, &session_id, &artifact_id, &target) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn artifact_delete_or_expire( + state: State<'_, AppState>, + session_id: String, + artifact_id: String, +) -> Result<(), String> { + let conn = state.db.lock().map_err(|error| error.to_string())?; + service()? + .expire(&conn, &session_id, &artifact_id) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn append_content_block(state: State<'_, AppState>, block: ContentBlock) -> Result<(), String> { + if !state.feature_flags.rich_content_write { + return Err("CONTENT_BLOCK_UNSUPPORTED".to_string()); + } + let conn = state.db.lock().map_err(|error| error.to_string())?; + MessageBlockService::append(&conn, &block, service()?.policy()) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn get_message_blocks( + state: State<'_, AppState>, + message_id: String, +) -> Result, String> { + if !state.feature_flags.rich_content_render { + return Ok(Vec::new()); + } + let conn = state.db.lock().map_err(|error| error.to_string())?; + MessageBlockRepo::find_by_message(&conn, &message_id).map_err(|error| error.to_string()) +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index f23e292..b05ee8d 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,3 +1,4 @@ +pub mod artifacts; pub mod chat; pub mod fs_explorer; pub mod mcp; diff --git a/src-tauri/src/commands/session.rs b/src-tauri/src/commands/session.rs index 4463926..8d60eee 100644 --- a/src-tauri/src/commands/session.rs +++ b/src-tauri/src/commands/session.rs @@ -7,7 +7,7 @@ use crate::db::models::{ExportData, ExportSession, ImportResult, MessageSearchRe use crate::db::repository::{ ArtifactRepo, MessageBlockRepo, MessageRepo, SessionRepo, WorkspaceRepo, }; -use crate::services::artifacts::RetentionState; +use crate::services::artifacts::{ArtifactService, ContentSafetyPolicy, RetentionState}; use crate::AppState; pub const WORKSPACE_KIND_DEFAULT: &str = "default"; @@ -140,6 +140,14 @@ pub fn update_session( pub async fn delete_session(state: State<'_, AppState>, id: String) -> Result<(), String> { let _binding_guard = state.workspace_terminal_guard.lock().await; let conn = state.db.lock().map_err(|e| e.to_string())?; + let artifact_service = ArtifactService::new( + config::artifacts_dir().map_err(|e| e.to_string())?, + ContentSafetyPolicy::default(), + ) + .map_err(|e| e.to_string())?; + artifact_service + .expire_session(&conn, &id) + .map_err(|e| e.to_string())?; SessionRepo::delete(&conn, &id).map_err(|e| e.to_string())?; drop(conn); state.terminal_manager.kill_chat_session(&id); diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index 09536d5..a5b889a 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -88,6 +88,12 @@ pub fn db_path() -> Result { Ok(config_dir()?.join("data").join("misaka.db")) } +/// Application-owned binary storage for rich-content artifacts. This is kept +/// outside workspaces, Skills and WebView data so only Rust resolves paths. +pub fn artifacts_dir() -> Result { + Ok(config_dir()?.join("data").join("artifacts")) +} + /// Get the skills directory path (~/.misakax/skills/) pub fn skills_dir() -> Result { Ok(config_dir()?.join("skills")) @@ -142,6 +148,7 @@ pub fn ensure_directories() -> Result<()> { let dirs = [ root.clone(), root.join("data"), + root.join("data").join("artifacts"), root.join("skills"), root.join("managed").join("skills"), root.join("managed").join("skills-staging"), diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4d76d11..e193fd3 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -151,6 +151,14 @@ pub fn run() { commands::chat::regenerate_message, commands::chat::generate_session_title, commands::chat::get_messages, + commands::artifacts::artifact_register, + commands::artifacts::artifact_get_metadata, + commands::artifacts::artifact_get_preview, + commands::artifacts::artifact_read_preview_base64, + commands::artifacts::artifact_export, + commands::artifacts::artifact_delete_or_expire, + commands::artifacts::append_content_block, + commands::artifacts::get_message_blocks, commands::fs_explorer::fs_list_dir, commands::fs_explorer::fs_read_text_file, commands::fs_explorer::fs_write_text_file, diff --git a/src-tauri/src/services/artifacts/mod.rs b/src-tauri/src/services/artifacts/mod.rs index 22145c2..711f5e3 100644 --- a/src-tauri/src/services/artifacts/mod.rs +++ b/src-tauri/src/services/artifacts/mod.rs @@ -1,5 +1,9 @@ +pub mod preview; +pub mod service; pub mod types; +pub use preview::{ArtifactPreview, PreviewKind, PreviewerRegistry}; +pub use service::{ArtifactService, ExportOutcome}; pub use types::{ ArtifactMetadata, ArtifactOrigin, ArtifactRecord, ContentSafetyPolicy, PreviewState, RetentionState, diff --git a/src-tauri/src/services/artifacts/preview.rs b/src-tauri/src/services/artifacts/preview.rs new file mode 100644 index 0000000..35032e2 --- /dev/null +++ b/src-tauri/src/services/artifacts/preview.rs @@ -0,0 +1,111 @@ +use serde::{Deserialize, Serialize}; + +use super::types::{ArtifactRecord, ContentSafetyPolicy, PreviewState}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum PreviewKind { + Text, + Csv, + Pdf, + Spreadsheet, + Document, + Image, + DownloadOnly, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ArtifactPreview { + pub kind: PreviewKind, + pub state: PreviewState, + pub message_key: Option, + pub text: Option, + pub truncated: bool, +} + +pub struct PreviewerRegistry; + +impl PreviewerRegistry { + pub fn preview_for( + artifact: &ArtifactRecord, + bytes: Option<&[u8]>, + policy: &ContentSafetyPolicy, + ) -> ArtifactPreview { + let kind = match artifact.media_type.as_str() { + "text/plain" | "text/markdown" | "application/json" => PreviewKind::Text, + "text/csv" => PreviewKind::Csv, + "application/pdf" => PreviewKind::Pdf, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => { + PreviewKind::Spreadsheet + } + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" => { + PreviewKind::Document + } + "image/png" | "image/jpeg" | "image/webp" | "image/gif" => PreviewKind::Image, + _ => PreviewKind::DownloadOnly, + }; + if artifact.byte_size > policy.max_preview_bytes { + return ArtifactPreview { + kind: PreviewKind::DownloadOnly, + state: PreviewState::Unsupported, + message_key: Some("richContent.preview.resourceLimit".to_string()), + text: None, + truncated: false, + }; + } + match kind { + PreviewKind::Text | PreviewKind::Csv => { + let text = bytes.and_then(|value| std::str::from_utf8(value).ok()); + match text { + Some(value) => { + let (text, truncated) = limit_text(value, policy); + ArtifactPreview { + kind, + state: PreviewState::Ready, + message_key: None, + text: Some(text), + truncated, + } + } + None => ArtifactPreview { + kind: PreviewKind::DownloadOnly, + state: PreviewState::Failed, + message_key: Some("richContent.preview.parseFailed".to_string()), + text: None, + truncated: false, + }, + } + } + PreviewKind::DownloadOnly => ArtifactPreview { + kind, + state: PreviewState::Unsupported, + message_key: Some("richContent.preview.unsupported".to_string()), + text: None, + truncated: false, + }, + _ => ArtifactPreview { + kind, + state: PreviewState::Ready, + message_key: None, + text: None, + truncated: false, + }, + } + } +} + +fn limit_text(value: &str, policy: &ContentSafetyPolicy) -> (String, bool) { + let mut output = String::new(); + let mut lines = 0usize; + for line in value.lines() { + if lines == policy.max_text_preview_lines + || output.len() + line.len() + 1 > policy.max_text_preview_chars + { + return (output, true); + } + output.push_str(line); + output.push('\n'); + lines += 1; + } + (output, false) +} diff --git a/src-tauri/src/services/artifacts/service.rs b/src-tauri/src/services/artifacts/service.rs new file mode 100644 index 0000000..82a1be6 --- /dev/null +++ b/src-tauri/src/services/artifacts/service.rs @@ -0,0 +1,622 @@ +use std::fs::{self, File, OpenOptions}; +use std::io::{Read, Write}; +use std::path::{Component, Path, PathBuf}; + +use anyhow::{anyhow, Context, Result}; +use base64::Engine; +use rusqlite::Connection; +use sha2::{Digest, Sha256}; + +use crate::db::repository::{ArtifactRepo, SessionRepo}; + +use super::preview::{ArtifactPreview, PreviewerRegistry}; +use super::types::{ + ArtifactMetadata, ArtifactOrigin, ArtifactRecord, ContentSafetyPolicy, PreviewState, + RetentionState, +}; + +#[derive(Debug, Clone, serde::Serialize)] +pub struct ExportOutcome { + pub status: String, + pub file_name: Option, +} + +pub struct ArtifactService { + root: PathBuf, + policy: ContentSafetyPolicy, +} + +impl ArtifactService { + pub fn new(root: PathBuf, policy: ContentSafetyPolicy) -> Result { + fs::create_dir_all(root.join("objects").join("sha256"))?; + fs::create_dir_all(root.join("staging"))?; + Ok(Self { root, policy }) + } + + pub fn policy(&self) -> &ContentSafetyPolicy { + &self.policy + } + + pub fn register_base64( + &self, + conn: &Connection, + session_id: String, + origin_message_id: Option, + origin_kind: ArtifactOrigin, + display_name: String, + declared_media_type: String, + bytes_base64: &str, + ) -> Result { + let bytes = base64::engine::general_purpose::STANDARD + .decode(bytes_base64) + .map_err(|_| anyhow!("ARTIFACT_TYPE_BLOCKED"))?; + self.register_bytes( + conn, + session_id, + origin_message_id, + origin_kind, + display_name, + declared_media_type, + &bytes, + ) + } + + #[allow(clippy::too_many_arguments)] + pub fn register_bytes( + &self, + conn: &Connection, + session_id: String, + origin_message_id: Option, + origin_kind: ArtifactOrigin, + display_name: String, + declared_media_type: String, + bytes: &[u8], + ) -> Result { + if session_id.trim().is_empty() + || bytes.is_empty() + || bytes.len() as u64 > self.policy.max_artifact_bytes + { + return Err(anyhow!("ARTIFACT_TOO_LARGE")); + } + // Authorize the owner before any file-system mutation. Artifact ingress never + // accepts a caller supplied path or creates data for a nonexistent session. + SessionRepo::find_by_id(conn, &session_id).context("ARTIFACT_ACCESS_DENIED")?; + if ArtifactRepo::active_bytes(conn)? + bytes.len() as u64 + > self.policy.max_total_artifact_bytes + { + return Err(anyhow!("ARTIFACT_STORAGE_QUOTA_EXCEEDED")); + } + let display_name = sanitize_display_name(&display_name)?; + let media_type = detect_media_type(bytes, &declared_media_type)?; + validate_image_dimensions(bytes, &media_type, self.policy.max_image_pixels)?; + + let sha256 = hex_hash(bytes); + let storage_key = format!( + "objects/sha256/{}/{}/{}", + &sha256[..2], + &sha256[2..4], + sha256 + ); + let path = self.resolve_storage_key(&storage_key)?; + let created_file = !path.exists(); + if created_file { + self.atomic_write(&path, bytes)?; + } + let now = chrono::Utc::now().to_rfc3339(); + let preview_state = match media_type.as_str() { + "image/png" + | "image/jpeg" + | "image/webp" + | "image/gif" + | "text/plain" + | "text/markdown" + | "application/json" + | "text/csv" + | "application/pdf" + | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" => { + PreviewState::None + } + _ => PreviewState::Unsupported, + }; + let record = ArtifactRecord { + artifact_id: uuid::Uuid::new_v4().to_string(), + owner_session_id: session_id, + origin_message_id, + origin_kind, + display_name, + media_type, + byte_size: bytes.len() as u64, + sha256, + storage_key, + preview_state, + preview_artifact_id: None, + retention_state: RetentionState::Active, + created_at: now, + expires_at: None, + }; + if let Err(error) = ArtifactRepo::insert(conn, &record) { + if created_file { + let _ = fs::remove_file(&path); + } + return Err(error); + } + Ok(ArtifactMetadata::from(&record)) + } + + pub fn metadata( + &self, + conn: &Connection, + session_id: &str, + artifact_id: &str, + ) -> Result { + let record = self.authorize(conn, session_id, artifact_id)?; + Ok(ArtifactMetadata::from(&record)) + } + + pub fn preview( + &self, + conn: &Connection, + session_id: &str, + artifact_id: &str, + ) -> Result { + let record = self.authorize(conn, session_id, artifact_id)?; + let bytes = if record.byte_size <= self.policy.max_preview_bytes { + Some(self.read_bytes(&record)?) + } else { + None + }; + Ok(PreviewerRegistry::preview_for( + &record, + bytes.as_deref(), + &self.policy, + )) + } + + pub fn read_preview_base64( + &self, + conn: &Connection, + session_id: &str, + artifact_id: &str, + ) -> Result { + let record = self.authorize(conn, session_id, artifact_id)?; + if record.byte_size > self.policy.max_preview_bytes { + return Err(anyhow!("PREVIEW_RESOURCE_LIMIT")); + } + Ok(base64::engine::general_purpose::STANDARD.encode(self.read_bytes(&record)?)) + } + + pub fn expire(&self, conn: &Connection, session_id: &str, artifact_id: &str) -> Result<()> { + let record = self.authorize(conn, session_id, artifact_id)?; + self.expire_record(conn, &record) + } + + pub fn expire_session(&self, conn: &Connection, session_id: &str) -> Result<()> { + for record in ArtifactRepo::find_by_sessions(conn, &[session_id.to_string()])? { + if record.retention_state == RetentionState::Active { + self.expire_record(conn, &record)?; + } + } + Ok(()) + } + + pub fn export_to_path( + &self, + conn: &Connection, + session_id: &str, + artifact_id: &str, + destination: &Path, + ) -> Result { + let record = self.authorize(conn, session_id, artifact_id)?; + if destination.exists() { + return Err(anyhow!("ARTIFACT_EXPORT_FAILED")); + } + let parent = destination + .parent() + .ok_or_else(|| anyhow!("ARTIFACT_EXPORT_FAILED"))?; + if !parent.is_dir() { + return Err(anyhow!("ARTIFACT_EXPORT_FAILED")); + } + let source = self.resolve_storage_key(&record.storage_key)?; + let mut input = File::open(source)?; + let mut output = OpenOptions::new() + .write(true) + .create_new(true) + .open(destination)?; + let mut hasher = Sha256::new(); + let mut buffer = [0u8; 64 * 1024]; + loop { + let count = input.read(&mut buffer)?; + if count == 0 { + break; + } + output.write_all(&buffer[..count])?; + hasher.update(&buffer[..count]); + } + output.sync_all()?; + let actual = format!("{:x}", hasher.finalize()); + if actual != record.sha256 { + let _ = fs::remove_file(destination); + return Err(anyhow!("ARTIFACT_HASH_MISMATCH")); + } + Ok(ExportOutcome { + status: "saved".to_string(), + file_name: destination + .file_name() + .and_then(|name| name.to_str()) + .map(str::to_string), + }) + } + + fn authorize( + &self, + conn: &Connection, + session_id: &str, + artifact_id: &str, + ) -> Result { + let record = ArtifactRepo::find_by_id(conn, artifact_id)?; + if record.owner_session_id != session_id { + return Err(anyhow!("ARTIFACT_ACCESS_DENIED")); + } + if record.retention_state != RetentionState::Active { + return Err(anyhow!("ARTIFACT_NOT_FOUND")); + } + Ok(record) + } + + fn read_bytes(&self, record: &ArtifactRecord) -> Result> { + let path = self.resolve_storage_key(&record.storage_key)?; + let bytes = fs::read(path).context("ARTIFACT_NOT_FOUND")?; + if bytes.len() as u64 != record.byte_size || hex_hash(&bytes) != record.sha256 { + return Err(anyhow!("ARTIFACT_HASH_MISMATCH")); + } + Ok(bytes) + } + + fn expire_record(&self, conn: &Connection, record: &ArtifactRecord) -> Result<()> { + ArtifactRepo::set_retention_state(conn, &record.artifact_id, RetentionState::Expired)?; + if !ArtifactRepo::has_active_storage_reference( + conn, + &record.storage_key, + &record.artifact_id, + )? { + let path = self.resolve_storage_key(&record.storage_key)?; + if path.exists() { + fs::remove_file(path)?; + } + } + Ok(()) + } + + fn atomic_write(&self, final_path: &Path, bytes: &[u8]) -> Result<()> { + let parent = final_path + .parent() + .ok_or_else(|| anyhow!("ARTIFACT_STORAGE_QUOTA_EXCEEDED"))?; + fs::create_dir_all(parent)?; + let staging = self + .root + .join("staging") + .join(format!("{}.part", uuid::Uuid::new_v4())); + { + let mut file = OpenOptions::new() + .write(true) + .create_new(true) + .open(&staging)?; + file.write_all(bytes)?; + file.sync_all()?; + } + fs::rename(&staging, final_path).or_else(|error| { + if final_path.exists() { + let _ = fs::remove_file(&staging); + Ok(()) + } else { + Err(error) + } + })?; + Ok(()) + } + + fn resolve_storage_key(&self, key: &str) -> Result { + let relative = Path::new(key); + if relative.is_absolute() + || relative.components().any(|component| { + matches!( + component, + Component::ParentDir | Component::RootDir | Component::Prefix(_) + ) + }) + { + return Err(anyhow!("ARTIFACT_ACCESS_DENIED")); + } + let path = self.root.join(relative); + if !path.starts_with(&self.root) { + return Err(anyhow!("ARTIFACT_ACCESS_DENIED")); + } + Ok(path) + } +} + +fn sanitize_display_name(input: &str) -> Result { + let name = Path::new(input) + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("") + .trim() + .replace(['/', '\\', ':', '*', '?', '"', '<', '>', '|'], "_"); + if name.is_empty() || name == "." || name == ".." || name.len() > 180 { + return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")); + } + Ok(name) +} + +fn detect_media_type(bytes: &[u8], declared: &str) -> Result { + let declared = declared.trim().to_ascii_lowercase(); + let detected = if bytes.starts_with(b"\x89PNG\r\n\x1a\n") { + "image/png" + } else if bytes.starts_with(&[0xff, 0xd8, 0xff]) { + "image/jpeg" + } else if bytes.starts_with(b"GIF87a") || bytes.starts_with(b"GIF89a") { + "image/gif" + } else if bytes.starts_with(b"RIFF") && bytes.get(8..12) == Some(b"WEBP") { + "image/webp" + } else if bytes.starts_with(b"%PDF-") { + "application/pdf" + } else if bytes.starts_with(b"PK\x03\x04") { + if contains_macro_project(bytes) { + return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")); + } + match declared.as_str() { + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" => { + declared.as_str() + } + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" => { + declared.as_str() + } + _ => return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")), + } + } else if is_safe_text(bytes) { + match declared.as_str() { + "text/plain" | "text/markdown" | "application/json" | "text/csv" => declared.as_str(), + _ => "text/plain", + } + } else { + return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")); + }; + if detected != declared && !(detected == "text/plain" && declared.is_empty()) { + return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")); + } + Ok(detected.to_string()) +} + +fn is_safe_text(bytes: &[u8]) -> bool { + let text = std::str::from_utf8(bytes).ok(); + text.is_some_and(|value| { + let lower = value.trim_start().to_ascii_lowercase(); + !lower.starts_with(" Result<()> { + if !matches!( + media_type, + "image/png" | "image/jpeg" | "image/gif" | "image/webp" + ) { + return Ok(()); + } + let dimensions = match media_type { + "image/png" if bytes.len() >= 24 => Some(( + u32::from_be_bytes(bytes[16..20].try_into().unwrap()) as u64, + u32::from_be_bytes(bytes[20..24].try_into().unwrap()) as u64, + )), + "image/gif" if bytes.len() >= 10 => Some(( + u16::from_le_bytes(bytes[6..8].try_into().unwrap()) as u64, + u16::from_le_bytes(bytes[8..10].try_into().unwrap()) as u64, + )), + "image/jpeg" => jpeg_dimensions(bytes), + "image/webp" => webp_dimensions(bytes), + _ => None, + }; + let Some((width, height)) = dimensions else { + return Err(anyhow!("ARTIFACT_TYPE_BLOCKED")); + }; + if width == 0 || height == 0 || width.saturating_mul(height) > max_pixels { + return Err(anyhow!("ARTIFACT_TOO_LARGE")); + } + Ok(()) +} + +fn contains_macro_project(bytes: &[u8]) -> bool { + bytes + .windows(b"vbaProject.bin".len()) + .any(|window| window.eq_ignore_ascii_case(b"vbaProject.bin")) +} + +fn jpeg_dimensions(bytes: &[u8]) -> Option<(u64, u64)> { + if !bytes.starts_with(&[0xff, 0xd8]) { + return None; + } + let mut index = 2usize; + while index + 9 <= bytes.len() { + while bytes.get(index) == Some(&0xff) { + index += 1; + } + let marker = *bytes.get(index)?; + index += 1; + if matches!(marker, 0xd8 | 0xd9) || (0xd0..=0xd7).contains(&marker) { + continue; + } + let segment_length = + u16::from_be_bytes([*bytes.get(index)?, *bytes.get(index + 1)?]) as usize; + if segment_length < 7 || index + segment_length > bytes.len() { + return None; + } + if matches!(marker, 0xc0..=0xc3 | 0xc5..=0xc7 | 0xc9..=0xcb | 0xcd..=0xcf) { + let height = u16::from_be_bytes([bytes[index + 3], bytes[index + 4]]) as u64; + let width = u16::from_be_bytes([bytes[index + 5], bytes[index + 6]]) as u64; + return Some((width, height)); + } + index += segment_length; + } + None +} + +fn webp_dimensions(bytes: &[u8]) -> Option<(u64, u64)> { + if bytes.get(0..4) != Some(b"RIFF") || bytes.get(8..12) != Some(b"WEBP") { + return None; + } + match bytes.get(12..16)? { + b"VP8X" if bytes.len() >= 30 => { + let width = 1 + u32::from_le_bytes([bytes[24], bytes[25], bytes[26], 0]) as u64; + let height = 1 + u32::from_le_bytes([bytes[27], bytes[28], bytes[29], 0]) as u64; + Some((width, height)) + } + b"VP8 " if bytes.len() >= 30 && bytes.get(23..26) == Some(&[0x9d, 0x01, 0x2a]) => { + let width = (u16::from_le_bytes([bytes[26], bytes[27]]) & 0x3fff) as u64; + let height = (u16::from_le_bytes([bytes[28], bytes[29]]) & 0x3fff) as u64; + Some((width, height)) + } + b"VP8L" if bytes.len() >= 25 && bytes[20] == 0x2f => { + let width = 1 + (bytes[21] as u16 | ((bytes[22] as u16 & 0x3f) << 8)) as u64; + let height = 1 + + ((bytes[22] as u16 >> 6) + | ((bytes[23] as u16) << 2) + | ((bytes[24] as u16 & 0x0f) << 10)) as u64; + Some((width, height)) + } + _ => None, + } +} + +fn hex_hash(bytes: &[u8]) -> String { + format!("{:x}", Sha256::digest(bytes)) +} + +#[cfg(test)] +mod tests { + use super::*; + use rusqlite::Connection; + + fn png(width: u32, height: u32) -> Vec { + let mut bytes = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR".to_vec(); + bytes.extend(width.to_be_bytes()); + bytes.extend(height.to_be_bytes()); + bytes.extend([8, 6, 0, 0, 0]); + bytes + } + + #[test] + fn blocks_cross_session_and_path_escape_access() { + let temp = tempfile::tempdir().unwrap(); + let service = + ArtifactService::new(temp.path().to_path_buf(), ContentSafetyPolicy::default()) + .unwrap(); + let conn = Connection::open_in_memory().unwrap(); + crate::db::migrations::run_migrations(&conn).unwrap(); + conn.execute("INSERT INTO sessions (id) VALUES ('session-a')", []) + .unwrap(); + let record = service + .register_bytes( + &conn, + "session-a".into(), + None, + ArtifactOrigin::Agent, + "chart.png".into(), + "image/png".into(), + &png(1, 1), + ) + .unwrap(); + assert!(service + .metadata(&conn, "session-b", &record.artifact_id) + .is_err()); + assert!(service.resolve_storage_key("../secret").is_err()); + } + + #[test] + fn rejects_svg_disguised_as_png() { + let temp = tempfile::tempdir().unwrap(); + let service = + ArtifactService::new(temp.path().to_path_buf(), ContentSafetyPolicy::default()) + .unwrap(); + let conn = Connection::open_in_memory().unwrap(); + crate::db::migrations::run_migrations(&conn).unwrap(); + conn.execute("INSERT INTO sessions (id) VALUES ('session')", []) + .unwrap(); + assert!(service + .register_bytes( + &conn, + "session".into(), + None, + ArtifactOrigin::Agent, + "bad.png".into(), + "image/png".into(), + b"", + ) + .is_err()); + } + + #[test] + fn rejects_an_oversized_pixel_header_before_preview() { + let temp = tempfile::tempdir().unwrap(); + let service = + ArtifactService::new(temp.path().to_path_buf(), ContentSafetyPolicy::default()) + .unwrap(); + let conn = Connection::open_in_memory().unwrap(); + crate::db::migrations::run_migrations(&conn).unwrap(); + conn.execute("INSERT INTO sessions (id) VALUES ('session')", []) + .unwrap(); + assert!(service + .register_bytes( + &conn, + "session".into(), + None, + ArtifactOrigin::Agent, + "large.png".into(), + "image/png".into(), + &png(100_000, 100_000), + ) + .is_err()); + } + + #[test] + fn expiration_removes_unreferenced_bytes_but_keeps_the_audit_record() { + let temp = tempfile::tempdir().unwrap(); + let service = + ArtifactService::new(temp.path().to_path_buf(), ContentSafetyPolicy::default()) + .unwrap(); + let conn = Connection::open_in_memory().unwrap(); + crate::db::migrations::run_migrations(&conn).unwrap(); + conn.execute("INSERT INTO sessions (id) VALUES ('session')", []) + .unwrap(); + let record = service + .register_bytes( + &conn, + "session".into(), + None, + ArtifactOrigin::Agent, + "chart.png".into(), + "image/png".into(), + &png(1, 1), + ) + .unwrap(); + let stored = service + .resolve_storage_key( + &ArtifactRepo::find_by_id(&conn, &record.artifact_id) + .unwrap() + .storage_key, + ) + .unwrap(); + assert!(stored.exists()); + + service + .expire(&conn, "session", &record.artifact_id) + .unwrap(); + + assert!(!stored.exists()); + assert!(service + .metadata(&conn, "session", &record.artifact_id) + .is_err()); + assert!(ArtifactRepo::find_by_id(&conn, &record.artifact_id).is_ok()); + } +} diff --git a/src/lib/ipc/artifacts.ts b/src/lib/ipc/artifacts.ts new file mode 100644 index 0000000..a5998f7 --- /dev/null +++ b/src/lib/ipc/artifacts.ts @@ -0,0 +1,27 @@ +import { invoke } from "./invoke"; +import type { + ArtifactExportOutcome, + ArtifactMetadata, + ArtifactPreview, + ArtifactRegisterRequest, + ContentBlock, +} from "./types"; + +export const artifactsIpc = { + register: (request: ArtifactRegisterRequest) => + invoke("artifact_register", { request }), + getMetadata: (sessionId: string, artifactId: string) => + invoke("artifact_get_metadata", { sessionId, artifactId }), + getPreview: (sessionId: string, artifactId: string) => + invoke("artifact_get_preview", { sessionId, artifactId }), + readPreviewBase64: (sessionId: string, artifactId: string) => + invoke("artifact_read_preview_base64", { sessionId, artifactId }), + export: (sessionId: string, artifactId: string) => + invoke("artifact_export", { sessionId, artifactId }), + expire: (sessionId: string, artifactId: string) => + invoke("artifact_delete_or_expire", { sessionId, artifactId }), + appendBlock: (block: ContentBlock) => + invoke("append_content_block", { block }), + getMessageBlocks: (messageId: string) => + invoke("get_message_blocks", { messageId }), +}; diff --git a/src/lib/ipc/index.ts b/src/lib/ipc/index.ts index db4beac..0143cc6 100644 --- a/src/lib/ipc/index.ts +++ b/src/lib/ipc/index.ts @@ -4,6 +4,7 @@ export { routerConfigsIpc } from "./router-configs"; export { workspaceIpc } from "./workspace"; export { sessionsIpc } from "./sessions"; export { chatIpc } from "./chat"; +export { artifactsIpc } from "./artifacts"; export { modelsIpc } from "./models"; export { sidecarIpc } from "./sidecar"; export { mcpIpc } from "./mcp"; From 1181618043fcd218cf42cfe0dad858134ca403b6 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:41:49 +0800 Subject: [PATCH 08/16] fix(rich-content): satisfy r1 clippy gate --- .../rich-content-delivery/06-implementation-log.md | 10 ++++++++++ src-tauri/src/services/artifacts/preview.rs | 4 +--- src-tauri/src/services/artifacts/service.rs | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index c37cc1f..eb340ae 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -131,6 +131,16 @@ - **风险/回滚:** 关闭 rich-content feature flags 可保持旧消息路径;删除 artifact 数据前会先将记录标为 expired,并只删除无 active 引用的字节文件。 - **下一步:** 提交、推送并等待远程 CI 全绿后,开始 R2。 +### 2026-08-09 — R1:远程 Clippy 兼容性修复 + +- **范围:** 修复 [CI #31272376136](https://github.com/knqiufan/MisakaX/actions/runs/31272376136) 暴露的 R1 lint;未改变 ArtifactService 的输入、存储、访问控制或 IPC 行为。 +- **代码审查:** `limit_text` 改用 `enumerate` 保持相同的零起始行数上限;`register_base64` 与已有 `register_bytes` 一样声明窄入口的多参数例外,避免为迎合 lint 而弱化 IPC 的显式字段。初始 R1 commit 的前端与三平台 Terminal Runtime 均通过,Rust 仅在 Clippy 阶段失败。 +- **验证:** `cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass;`cargo test --lib artifact` → 7 passed / 0 failed。 +- **Git:** `ab7f1ee` 已推送;本条记录随 R1 Clippy 修复提交推送。 +- **远程 CI:** 待修复提交推送后重新运行。 +- **风险/回滚:** 仅 lint 等价改动,可单独回退。 +- **下一步:** 等待 R1 required CI 全绿后进入 R2。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/src/services/artifacts/preview.rs b/src-tauri/src/services/artifacts/preview.rs index 35032e2..bf72cb5 100644 --- a/src-tauri/src/services/artifacts/preview.rs +++ b/src-tauri/src/services/artifacts/preview.rs @@ -96,8 +96,7 @@ impl PreviewerRegistry { fn limit_text(value: &str, policy: &ContentSafetyPolicy) -> (String, bool) { let mut output = String::new(); - let mut lines = 0usize; - for line in value.lines() { + for (lines, line) in value.lines().enumerate() { if lines == policy.max_text_preview_lines || output.len() + line.len() + 1 > policy.max_text_preview_chars { @@ -105,7 +104,6 @@ fn limit_text(value: &str, policy: &ContentSafetyPolicy) -> (String, bool) { } output.push_str(line); output.push('\n'); - lines += 1; } (output, false) } diff --git a/src-tauri/src/services/artifacts/service.rs b/src-tauri/src/services/artifacts/service.rs index 82a1be6..a5eff7a 100644 --- a/src-tauri/src/services/artifacts/service.rs +++ b/src-tauri/src/services/artifacts/service.rs @@ -37,6 +37,7 @@ impl ArtifactService { &self.policy } + #[allow(clippy::too_many_arguments)] pub fn register_base64( &self, conn: &Connection, From 53a079d4c315463680ce15626c56b69e9ba6431b Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:48:31 +0800 Subject: [PATCH 09/16] fix(rich-content): authorize r1 artifact commands --- src-tauri/build.rs | 8 ++ src-tauri/gen/schemas/acl-manifests.json | 2 +- src-tauri/gen/schemas/desktop-schema.json | 96 +++++++++++++++++++++++ src-tauri/gen/schemas/windows-schema.json | 96 +++++++++++++++++++++++ src-tauri/permissions/main.toml | 8 ++ 5 files changed, 209 insertions(+), 1 deletion(-) diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 251140c..e18f551 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -102,6 +102,14 @@ const COMMANDS: &[&str] = &[ "skills_download_remote", "skills_set_enabled", "skills_uninstall", + "artifact_register", + "artifact_get_metadata", + "artifact_get_preview", + "artifact_read_preview_base64", + "artifact_export", + "artifact_delete_or_expire", + "append_content_block", + "get_message_blocks", ]; fn main() { diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index e6c3730..99388fd 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-append-content-block":{"identifier":"allow-append-content-block","description":"Enables the append_content_block command without any pre-configured scope.","commands":{"allow":["append_content_block"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-artifact-delete-or-expire":{"identifier":"allow-artifact-delete-or-expire","description":"Enables the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":["artifact_delete_or_expire"],"deny":[]}},"allow-artifact-export":{"identifier":"allow-artifact-export","description":"Enables the artifact_export command without any pre-configured scope.","commands":{"allow":["artifact_export"],"deny":[]}},"allow-artifact-get-metadata":{"identifier":"allow-artifact-get-metadata","description":"Enables the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":["artifact_get_metadata"],"deny":[]}},"allow-artifact-get-preview":{"identifier":"allow-artifact-get-preview","description":"Enables the artifact_get_preview command without any pre-configured scope.","commands":{"allow":["artifact_get_preview"],"deny":[]}},"allow-artifact-read-preview-base64":{"identifier":"allow-artifact-read-preview-base64","description":"Enables the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":["artifact_read_preview_base64"],"deny":[]}},"allow-artifact-register":{"identifier":"allow-artifact-register","description":"Enables the artifact_register command without any pre-configured scope.","commands":{"allow":["artifact_register"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-message-blocks":{"identifier":"allow-get-message-blocks","description":"Enables the get_message_blocks command without any pre-configured scope.","commands":{"allow":["get_message_blocks"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-append-content-block":{"identifier":"deny-append-content-block","description":"Denies the append_content_block command without any pre-configured scope.","commands":{"allow":[],"deny":["append_content_block"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-artifact-delete-or-expire":{"identifier":"deny-artifact-delete-or-expire","description":"Denies the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_delete_or_expire"]}},"deny-artifact-export":{"identifier":"deny-artifact-export","description":"Denies the artifact_export command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_export"]}},"deny-artifact-get-metadata":{"identifier":"deny-artifact-get-metadata","description":"Denies the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_metadata"]}},"deny-artifact-get-preview":{"identifier":"deny-artifact-get-preview","description":"Denies the artifact_get_preview command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_preview"]}},"deny-artifact-read-preview-base64":{"identifier":"deny-artifact-read-preview-base64","description":"Denies the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_read_preview_base64"]}},"deny-artifact-register":{"identifier":"deny-artifact-register","description":"Denies the artifact_register command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_register"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-message-blocks":{"identifier":"deny-get-message-blocks","description":"Denies the get_message_blocks command without any pre-configured scope.","commands":{"allow":[],"deny":["get_message_blocks"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall","artifact_register","artifact_get_metadata","artifact_get_preview","artifact_read_preview_base64","artifact_export","artifact_delete_or_expire","append_content_block","get_message_blocks"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 7134af6..6543194 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -392,12 +392,54 @@ "const": "allow-add-custom-model", "markdownDescription": "Enables the add_custom_model command without any pre-configured scope." }, + { + "description": "Enables the append_content_block command without any pre-configured scope.", + "type": "string", + "const": "allow-append-content-block", + "markdownDescription": "Enables the append_content_block command without any pre-configured scope." + }, { "description": "Enables the archive_session command without any pre-configured scope.", "type": "string", "const": "allow-archive-session", "markdownDescription": "Enables the archive_session command without any pre-configured scope." }, + { + "description": "Enables the artifact_delete_or_expire command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-delete-or-expire", + "markdownDescription": "Enables the artifact_delete_or_expire command without any pre-configured scope." + }, + { + "description": "Enables the artifact_export command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-export", + "markdownDescription": "Enables the artifact_export command without any pre-configured scope." + }, + { + "description": "Enables the artifact_get_metadata command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-get-metadata", + "markdownDescription": "Enables the artifact_get_metadata command without any pre-configured scope." + }, + { + "description": "Enables the artifact_get_preview command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-get-preview", + "markdownDescription": "Enables the artifact_get_preview command without any pre-configured scope." + }, + { + "description": "Enables the artifact_read_preview_base64 command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-read-preview-base64", + "markdownDescription": "Enables the artifact_read_preview_base64 command without any pre-configured scope." + }, + { + "description": "Enables the artifact_register command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-register", + "markdownDescription": "Enables the artifact_register command without any pre-configured scope." + }, { "description": "Enables the backfill_session_workspaces command without any pre-configured scope.", "type": "string", @@ -500,6 +542,12 @@ "const": "allow-get-app-config", "markdownDescription": "Enables the get_app_config command without any pre-configured scope." }, + { + "description": "Enables the get_message_blocks command without any pre-configured scope.", + "type": "string", + "const": "allow-get-message-blocks", + "markdownDescription": "Enables the get_message_blocks command without any pre-configured scope." + }, { "description": "Enables the get_messages command without any pre-configured scope.", "type": "string", @@ -1010,12 +1058,54 @@ "const": "deny-add-custom-model", "markdownDescription": "Denies the add_custom_model command without any pre-configured scope." }, + { + "description": "Denies the append_content_block command without any pre-configured scope.", + "type": "string", + "const": "deny-append-content-block", + "markdownDescription": "Denies the append_content_block command without any pre-configured scope." + }, { "description": "Denies the archive_session command without any pre-configured scope.", "type": "string", "const": "deny-archive-session", "markdownDescription": "Denies the archive_session command without any pre-configured scope." }, + { + "description": "Denies the artifact_delete_or_expire command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-delete-or-expire", + "markdownDescription": "Denies the artifact_delete_or_expire command without any pre-configured scope." + }, + { + "description": "Denies the artifact_export command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-export", + "markdownDescription": "Denies the artifact_export command without any pre-configured scope." + }, + { + "description": "Denies the artifact_get_metadata command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-get-metadata", + "markdownDescription": "Denies the artifact_get_metadata command without any pre-configured scope." + }, + { + "description": "Denies the artifact_get_preview command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-get-preview", + "markdownDescription": "Denies the artifact_get_preview command without any pre-configured scope." + }, + { + "description": "Denies the artifact_read_preview_base64 command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-read-preview-base64", + "markdownDescription": "Denies the artifact_read_preview_base64 command without any pre-configured scope." + }, + { + "description": "Denies the artifact_register command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-register", + "markdownDescription": "Denies the artifact_register command without any pre-configured scope." + }, { "description": "Denies the backfill_session_workspaces command without any pre-configured scope.", "type": "string", @@ -1118,6 +1208,12 @@ "const": "deny-get-app-config", "markdownDescription": "Denies the get_app_config command without any pre-configured scope." }, + { + "description": "Denies the get_message_blocks command without any pre-configured scope.", + "type": "string", + "const": "deny-get-message-blocks", + "markdownDescription": "Denies the get_message_blocks command without any pre-configured scope." + }, { "description": "Denies the get_messages command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/windows-schema.json b/src-tauri/gen/schemas/windows-schema.json index 7134af6..6543194 100644 --- a/src-tauri/gen/schemas/windows-schema.json +++ b/src-tauri/gen/schemas/windows-schema.json @@ -392,12 +392,54 @@ "const": "allow-add-custom-model", "markdownDescription": "Enables the add_custom_model command without any pre-configured scope." }, + { + "description": "Enables the append_content_block command without any pre-configured scope.", + "type": "string", + "const": "allow-append-content-block", + "markdownDescription": "Enables the append_content_block command without any pre-configured scope." + }, { "description": "Enables the archive_session command without any pre-configured scope.", "type": "string", "const": "allow-archive-session", "markdownDescription": "Enables the archive_session command without any pre-configured scope." }, + { + "description": "Enables the artifact_delete_or_expire command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-delete-or-expire", + "markdownDescription": "Enables the artifact_delete_or_expire command without any pre-configured scope." + }, + { + "description": "Enables the artifact_export command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-export", + "markdownDescription": "Enables the artifact_export command without any pre-configured scope." + }, + { + "description": "Enables the artifact_get_metadata command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-get-metadata", + "markdownDescription": "Enables the artifact_get_metadata command without any pre-configured scope." + }, + { + "description": "Enables the artifact_get_preview command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-get-preview", + "markdownDescription": "Enables the artifact_get_preview command without any pre-configured scope." + }, + { + "description": "Enables the artifact_read_preview_base64 command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-read-preview-base64", + "markdownDescription": "Enables the artifact_read_preview_base64 command without any pre-configured scope." + }, + { + "description": "Enables the artifact_register command without any pre-configured scope.", + "type": "string", + "const": "allow-artifact-register", + "markdownDescription": "Enables the artifact_register command without any pre-configured scope." + }, { "description": "Enables the backfill_session_workspaces command without any pre-configured scope.", "type": "string", @@ -500,6 +542,12 @@ "const": "allow-get-app-config", "markdownDescription": "Enables the get_app_config command without any pre-configured scope." }, + { + "description": "Enables the get_message_blocks command without any pre-configured scope.", + "type": "string", + "const": "allow-get-message-blocks", + "markdownDescription": "Enables the get_message_blocks command without any pre-configured scope." + }, { "description": "Enables the get_messages command without any pre-configured scope.", "type": "string", @@ -1010,12 +1058,54 @@ "const": "deny-add-custom-model", "markdownDescription": "Denies the add_custom_model command without any pre-configured scope." }, + { + "description": "Denies the append_content_block command without any pre-configured scope.", + "type": "string", + "const": "deny-append-content-block", + "markdownDescription": "Denies the append_content_block command without any pre-configured scope." + }, { "description": "Denies the archive_session command without any pre-configured scope.", "type": "string", "const": "deny-archive-session", "markdownDescription": "Denies the archive_session command without any pre-configured scope." }, + { + "description": "Denies the artifact_delete_or_expire command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-delete-or-expire", + "markdownDescription": "Denies the artifact_delete_or_expire command without any pre-configured scope." + }, + { + "description": "Denies the artifact_export command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-export", + "markdownDescription": "Denies the artifact_export command without any pre-configured scope." + }, + { + "description": "Denies the artifact_get_metadata command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-get-metadata", + "markdownDescription": "Denies the artifact_get_metadata command without any pre-configured scope." + }, + { + "description": "Denies the artifact_get_preview command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-get-preview", + "markdownDescription": "Denies the artifact_get_preview command without any pre-configured scope." + }, + { + "description": "Denies the artifact_read_preview_base64 command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-read-preview-base64", + "markdownDescription": "Denies the artifact_read_preview_base64 command without any pre-configured scope." + }, + { + "description": "Denies the artifact_register command without any pre-configured scope.", + "type": "string", + "const": "deny-artifact-register", + "markdownDescription": "Denies the artifact_register command without any pre-configured scope." + }, { "description": "Denies the backfill_session_workspaces command without any pre-configured scope.", "type": "string", @@ -1118,6 +1208,12 @@ "const": "deny-get-app-config", "markdownDescription": "Denies the get_app_config command without any pre-configured scope." }, + { + "description": "Denies the get_message_blocks command without any pre-configured scope.", + "type": "string", + "const": "deny-get-message-blocks", + "markdownDescription": "Denies the get_message_blocks command without any pre-configured scope." + }, { "description": "Denies the get_messages command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/permissions/main.toml b/src-tauri/permissions/main.toml index bd6ddb8..59f20f8 100644 --- a/src-tauri/permissions/main.toml +++ b/src-tauri/permissions/main.toml @@ -100,4 +100,12 @@ commands.allow = [ "skills_download_remote", "skills_set_enabled", "skills_uninstall", + "artifact_register", + "artifact_get_metadata", + "artifact_get_preview", + "artifact_read_preview_base64", + "artifact_export", + "artifact_delete_or_expire", + "append_content_block", + "get_message_blocks", ] From 6c7e5de1617abefc9e8e15ae02b98e856b169cde Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 02:59:50 +0800 Subject: [PATCH 10/16] docs(rich-content): record r1 CI gate --- .../06-implementation-log.md | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index eb340ae..4ccda4a 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0 已通过远程全量 CI。R1 ArtifactService 后端交付已完成本地验证,待提交、推送与远程 CI;R2–R4 仍未开始阶段提交。 +> **状态:** R0、R1 已通过远程全量 CI。R2–R4 尚未开始阶段提交;工作区中保留的后续候选实现不得视为已验收交付。 --- @@ -21,10 +21,10 @@ | 阶段 | 状态 | 负责人 | 开始 | 完成 | 证据/备注 | |---|---|---|---|---|---| | R0 契约/安全基线 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `b1ed884`;[CI #31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 的 8 项检查全绿 | -| R1 ArtifactService/图片/下载 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限 ArtifactService、窄 IPC、原生保存与会话过期清理;待 commit/push/CI | -| R2 文件预览 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 本地只读预览、资源上限和下载回退;未 commit/push/CI | -| R3 图表 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 受限 spec、ARIA、表格与 CSV 产物导出;未 commit/push/CI | -| R4 地图 | 本地实现完成,待门禁 | 当前实施者 | 2026-08-09 | 2026-08-09 | 仅本地 GeoJSON/no tiles;R4b 未开始;未 commit/push/CI | +| R1 ArtifactService/图片/下载 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `53a079d`;[CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 8 项检查全绿 | +| R2 文件预览 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送 | +| R3 图表 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送 | +| R4 地图 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送;R4b 不在范围内 | | R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | | R6 加固/发布 | 未开始 | 待分配 | — | — | 三平台/沙箱 gate;通过阶段门禁后完成 | @@ -126,10 +126,10 @@ - **代码审查:** Artifact 路径只由 Rust 从 application data 目录解析;写入在 session 存在性校验后才执行;导出使用原生 dialog 并验证写出哈希;未添加 WebView FS/HTTP/Shell permission 或 URL/path 入口。会话删除前过期所属 artifact,保留数据库审计记录。 - **验证:** `cargo fmt --check` → pass;`cargo check` → pass;`cargo test --lib artifact` → 7 passed / 0 failed。 - **未验证:** R1 不接入重型前端 renderer;图像放大/通用文件 preview 将由 R2 覆盖。 -- **Git:** 待提交(仅 R1 后端及 IPC 文件)。 -- **远程 CI:** 待当前 R1 提交推送后运行。 +- **Git:** `ab7f1ee`(后端/IPC)、`1181618`(Clippy)、`53a079d`(命令 manifest 与权限白名单)均已非强制推送至 `origin/codex/rich-content-r0-r4`。 +- **远程 CI:** [CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 Rust、Frontend、三平台 Terminal Runtime 与三平台 Tauri Build 共 8 项检查全绿。 - **风险/回滚:** 关闭 rich-content feature flags 可保持旧消息路径;删除 artifact 数据前会先将记录标为 expired,并只删除无 active 引用的字节文件。 -- **下一步:** 提交、推送并等待远程 CI 全绿后,开始 R2。 +- **下一步:** R1 已完成;可开始 R2 的独立阶段审查与实现收口。 ### 2026-08-09 — R1:远程 Clippy 兼容性修复 @@ -137,9 +137,21 @@ - **代码审查:** `limit_text` 改用 `enumerate` 保持相同的零起始行数上限;`register_base64` 与已有 `register_bytes` 一样声明窄入口的多参数例外,避免为迎合 lint 而弱化 IPC 的显式字段。初始 R1 commit 的前端与三平台 Terminal Runtime 均通过,Rust 仅在 Clippy 阶段失败。 - **验证:** `cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass;`cargo test --lib artifact` → 7 passed / 0 failed。 - **Git:** `ab7f1ee` 已推送;本条记录随 R1 Clippy 修复提交推送。 -- **远程 CI:** 待修复提交推送后重新运行。 +- **远程 CI:** 修复后的运行先在 [CI #31272566088](https://github.com/knqiufan/MisakaX/actions/runs/31272566088) 通过 Clippy,但安全基线发现注册命令未同步至 Tauri AppManifest/权限白名单;补充修复后,最终 [CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 8/8 成功。 - **风险/回滚:** 仅 lint 等价改动,可单独回退。 -- **下一步:** 等待 R1 required CI 全绿后进入 R2。 +- **下一步:** R1 required CI 已全绿,可进入 R2。 + +### 2026-08-09 — R1:命令清单/权限同步与阶段完成 + +- **范围:** 将 R1 新注册的 artifact 与 content-block 命令同步至受控 AppManifest、`main-commands` 最小权限白名单及生成 schema;未引入通用 FS、HTTP 或 Shell 权限,也未混入 R2–R4 UI/依赖。 +- **代码审查:** 对照 `invoke_handler`、`build.rs` 和 `permissions/main.toml` 三处命令集合,确认 8 个 artifact/block 命令均为 Rust 窄接口,终端权限集不变。安全基线的集合一致性测试修复后通过。 +- **验证:** `cargo fmt --check` → pass;`cargo test --all-features --test security_config_baseline_tests` → 5 passed / 0 failed。 +- **未验证:** 未进行 R2–R4 的 preview/renderer 手工场景;这些内容未纳入 R1 提交。 +- **Git:** `53a079d`(`fix(rich-content): authorize r1 artifact commands`)已非强制推送至 `origin/codex/rich-content-r0-r4`。 +- **远程 CI:** [CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) completed/success;8 个 required 作业均成功,R1 阶段门禁已满足。 +- **风险/回滚:** 回滚 `53a079d` 会恢复安全基线拒绝行为,且不能保留 R1 的注册命令;正常回滚 R1 时应将服务和该权限提交一并回退。 +- **文档同步:** 本实施记录的阶段看板和 R1 证据更新。 +- **下一步:** 开始 R2;先把候选工作区改动收口为仅文件预览、图片展示与下载回退,再执行独立审查、测试、commit/push/CI。 ## 后续记录模板 From 2e979e1c0a869b9941e2a9b3e6feb14a80073ad7 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 08:15:49 +0800 Subject: [PATCH 11/16] feat(rich-content): complete r2 file previews --- docs/design/frontend-ui-guidelines.md | 10 +- .../06-implementation-log.md | 17 +- package-lock.json | 612 ++++++++++++++++++ package.json | 3 + src/components/chat/message/MessageItem.tsx | 7 +- .../chat-content/MessageContentBlocks.tsx | 53 ++ src/features/chat-content/RichContentCard.tsx | 49 ++ .../chat-content/renderer-registry.tsx | 29 + .../renderers/ArtifactBlockRenderer.tsx | 81 +++ .../renderers/ArtifactPreviewDialog.tsx | 301 +++++++++ .../renderers/ImageBlockRenderer.tsx | 46 ++ .../renderers/MarkdownBlockRenderer.tsx | 10 + .../renderers/NoticeBlockRenderer.tsx | 25 + src/features/chat-content/types.ts | 61 ++ src/locales/en/chat.json | 63 ++ src/locales/zh-CN/chat.json | 63 ++ src/types/mammoth.browser.d.ts | 3 + 17 files changed, 1429 insertions(+), 4 deletions(-) create mode 100644 src/features/chat-content/MessageContentBlocks.tsx create mode 100644 src/features/chat-content/RichContentCard.tsx create mode 100644 src/features/chat-content/renderer-registry.tsx create mode 100644 src/features/chat-content/renderers/ArtifactBlockRenderer.tsx create mode 100644 src/features/chat-content/renderers/ArtifactPreviewDialog.tsx create mode 100644 src/features/chat-content/renderers/ImageBlockRenderer.tsx create mode 100644 src/features/chat-content/renderers/MarkdownBlockRenderer.tsx create mode 100644 src/features/chat-content/renderers/NoticeBlockRenderer.tsx create mode 100644 src/features/chat-content/types.ts create mode 100644 src/types/mammoth.browser.d.ts diff --git a/docs/design/frontend-ui-guidelines.md b/docs/design/frontend-ui-guidelines.md index cbed85f..de264b8 100644 --- a/docs/design/frontend-ui-guidelines.md +++ b/docs/design/frontend-ui-guidelines.md @@ -8,7 +8,7 @@ - **按钮、下拉菜单、Popover、Select、Dialog、Tooltip 等控件的细节与变体**:编写或调整时须同时对照 [button-menu-design-spec.md](./button-menu-design-spec.md)。 - **可复刻参考(CodePilot)**:[`docs/ui/02-chat.md`](../ui/02-chat.md)、[`docs/ui/03-workspace.md`](../ui/03-workspace.md)、[`docs/ui/04-settings.md`](../ui/04-settings.md)、[`docs/ui/06-markdown-message-tools.md`](../ui/06-markdown-message-tools.md)(视觉与能力对齐;IA 以 shell 规范本期边界为准)。 -**最后审阅 / Last reviewed:** 2026-08-07(v32) +**最后审阅 / Last reviewed:** 2026-08-09(v33) ## 1. 设计理念 (Design Philosophy) @@ -207,6 +207,14 @@ MisakaX 的目标是打造一个**现代化、专业、克制的桌面端 Agent - 主列已由 `MessageList` 的 `max-w-3xl` 约束;Assistant **不再**套 `surface-card` 底色卡片。 - 禁止用卡片底与 User 气泡混淆。 +### 4.6.x.1 富内容块(Rich Content Blocks) + +- 富内容是 Assistant 正文中的**有序内容块**,不是新的整条消息气泡;Assistant 外层仍保持无背景、无圆角外壳。无块或功能开关关闭时必须回退到既有 Markdown 正文。 +- 每个独立块使用 `my-4 rounded-xl border-border/40 bg-muted/20` 的低对比容器,头部使用 `size-4` Lucide 图标、`text-sm font-medium` 标题和紧凑 `icon-xs` 操作;禁止 dashboard 式强色背景、悬停位移或缩放。 +- 图表、地图、文件预览必须惰性加载,并提供受控的文本/数据/下载降级路径;块级失败只能显示局部 notice,不能中断相邻 Markdown、工具调用或消息 footer。 +- 文件预览使用共享 `Dialog`,始终标明“只读”;二进制资源仅经窄 IPC 获取,禁止在 JSX 注入 HTML、任意 URL、`file:` 路径或未验证 SVG。所有可见标签、状态、`aria-label` 和错误文案必须走 `chat.richContent.*` i18n key。 +- 图表和地图的辅助操作(数据表、要素列表、复制、导出)必须键盘可达;颜色不是唯一信息来源,库加载/WebGL 失败时显示等价文本数据。 + ### 4.6.y 工具调用状态行(ToolActionsGroup) - 主路径为左色线分组 + 紧凑行;pending 用静态圆点(`size-2 rounded-full bg-muted-foreground/40`),running 用 **中性** spinner(`text-muted-foreground`,禁止蓝色品牌 spinner)。 diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index 4ccda4a..eb6c93d 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0、R1 已通过远程全量 CI。R2–R4 尚未开始阶段提交;工作区中保留的后续候选实现不得视为已验收交付。 +> **状态:** R0、R1 已通过远程全量 CI。R2 文件预览已完成本地验证,待阶段提交、推送与远程 CI;R3–R4 尚未开始阶段提交。 --- @@ -22,7 +22,7 @@ |---|---|---|---|---|---| | R0 契约/安全基线 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `b1ed884`;[CI #31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 的 8 项检查全绿 | | R1 ArtifactService/图片/下载 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `53a079d`;[CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 8 项检查全绿 | -| R2 文件预览 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送 | +| R2 文件预览 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 惰性只读预览、图片 Dialog 与下载回退;待 commit/push/CI | | R3 图表 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送 | | R4 地图 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送;R4b 不在范围内 | | R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | @@ -153,6 +153,19 @@ - **文档同步:** 本实施记录的阶段看板和 R1 证据更新。 - **下一步:** 开始 R2;先把候选工作区改动收口为仅文件预览、图片展示与下载回退,再执行独立审查、测试、commit/push/CI。 +### 2026-08-09 — R2:本地文件预览、图片查看与下载回退 + +- **范围:** 在 Assistant 消息中接入有序内容块 dispatcher、Artifact/图片卡和只读预览 Dialog。文本、CSV、PDF、XLSX 与 DOCX 仅在用户打开预览后动态加载;未支持或解析失败的文件保留原件下载。图表/地图 renderer 与其导出 IPC 不在本阶段提交。 +- **修改:** 新增 `src/features/chat-content/` 的 R2 renderer、payload reader 与 block ErrorBoundary;`MessageItem` 在有 blocks 时走有序 renderer、无 blocks 时保持 Markdown;新增 PDF.js、SheetJS、Mammoth 依赖及浏览器声明,补齐双语 `chat.richContent.*` 文案和 UI 规范。 +- **代码审查:** 确认 Renderer Registry 对 chart/map 仍映射到非执行 notice;文件 bytes 只能经 artifact 窄 IPC 获取,未接受路径、`file:`、HTML、SVG 或远端 URL;DOCX 仅抽取 DOM `textContent`,不注入转换出的 HTML。每个块由 ErrorBoundary 隔离,图片/文档失败不会中断相邻 Markdown。发现阶段拆分后未提交的 R3/R4 renderer 仍需其导出 IPC 类型,已保留在未暂存候选切片中,未混入 R2。 +- **验证:** `npm run build` → pass(Vite 提示部分动态依赖 chunk 大于 500 kB,未阻塞);`npm test -- --run` → 38 files / 271 passed。Vitest/JSDOM 输出 `HTMLCanvasElement.getContext` 未实现诊断,但测试进程 exit 0。 +- **未验证:** 未执行三平台人工 PDF/XLSX/DOCX/图片预览、恶意加密 Office/压缩炸弹压测或屏幕阅读器实测;不把这些未执行项当作通过。R3/R4 renderer 尚未进行阶段审查、提交或推送。 +- **Git:** 待提交;暂存范围仅限 R2 UI、预览依赖、i18n、设计规范与本记录。 +- **远程 CI:** 待 R2 commit 推送后运行。 +- **风险/回滚:** 移除 R2 renderer/依赖即可恢复 R1 的后端 artifact 能力;关闭 `MISAKAX_RICH_CONTENT_RENDER` 继续显示 legacy Markdown。预览始终为只读,任何失败保留下载路径。 +- **文档同步:** `docs/design/frontend-ui-guidelines.md` §4.6.x.1;本实施记录。 +- **下一步:** 审查暂存差异、提交 R2 并等待 remote CI 全绿;随后才能开始 R3。 + ## 后续记录模板 ```markdown diff --git a/package-lock.json b/package-lock.json index 5e39a1f..4e3052b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,10 @@ "clsx": "^2.1.1", "i18next": "^26.0.8", "lucide-react": "^1.14.0", + "mammoth": "^1.12.0", "monaco-editor": "^0.55.1", "next-themes": "^0.4.6", + "pdfjs-dist": "^6.2.108", "radix-ui": "^1.4.3", "react": "^19", "react-dom": "^19", @@ -43,6 +45,7 @@ "streamdown": "^2.5.0", "tailwind-merge": "^3.5.0", "tailwindcss": "^4.2.4", + "xlsx": "^0.18.5", "zustand": "^5.0.12" }, "devDependencies": { @@ -1162,6 +1165,271 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@napi-rs/canvas": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-1.0.3.tgz", + "integrity": "sha512-OlI657a5XXvKGFX7kNeIzJ8rO7IXt87Mqu2H8rXE46viAuOfum/JA7ysX7+eBhxNKznT+RCZh418mndlcFX3+w==", + "license": "MIT", + "optional": true, + "workspaces": [ + "e2e/*" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "1.0.3", + "@napi-rs/canvas-darwin-arm64": "1.0.3", + "@napi-rs/canvas-darwin-x64": "1.0.3", + "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.3", + "@napi-rs/canvas-linux-arm64-gnu": "1.0.3", + "@napi-rs/canvas-linux-arm64-musl": "1.0.3", + "@napi-rs/canvas-linux-riscv64-gnu": "1.0.3", + "@napi-rs/canvas-linux-x64-gnu": "1.0.3", + "@napi-rs/canvas-linux-x64-musl": "1.0.3", + "@napi-rs/canvas-win32-arm64-msvc": "1.0.3", + "@napi-rs/canvas-win32-x64-msvc": "1.0.3" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-1.0.3.tgz", + "integrity": "sha512-7kSCdUhoXiO+AaIMXdBGdtp6EctZNkmF62Rea/BmVQlwKaM3bBhOzyGUzxyxz9dv5vdBfpyAaxhSRSJF4kqK4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-ds14V1BPagLszQyaDTeggny5fNeTCqsUQ5QhFj9VDxSEfzrVxXtdbR0LoFyKa0Siaaw8KvqSk4t7k/WoZJwvbg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-1.0.3.tgz", + "integrity": "sha512-qof3LRAAycmkV2I1izZo9RoSHF8kCQr5O05sFwv0jK8rSdYV6KHVwimo6Qb7RxZj40WHKbLHm5JDaUF0o5XUAA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-FU2kKZLmolHA9+KcUA+l1+xH3WTLUUTQDU/kLv9SEUr2TrRPu94aytOeizFJDHPs/QBcw4QL1mCQhetQXYBbag==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-GVSjntxKeA+/y/ZKf1F+cmUw1WeIkE5aMRPqnZUlBTBvBcrvgWccJAWuYCKPX4QJQwZILIIwhgdAbl51yj6fpA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-J51oK/axyZ13kxycumSMfLiDZMdWdOVvqDFI28BpuViZHE3A0bQfr8B5vg8YnPEnqLD3BSn1hkdlh2buspEcNQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-1.0.3.tgz", + "integrity": "sha512-CtQgQjoVTX67jS9XuCTtJ40Sl7wRLMguoFnnGnfDmCWf7kzKFZVwj5ynqUOIGKFMSB61ZCuQlwPvVNxYTTseaw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-jtfzAHFp+FRaR7zGT4jyCe6wUgAG/dVb5A4Apd8FY9jKarntDfUAlJXscugiH7ZF5kKnu7/lHFk9LaDPcrGEVQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-xTzaUCKUHTY4bCGadeeRZggbRVbGUT1petg7Z8r9AJR2+D9Bqu6nQAgqBGC6D47tA70LjaaaLTrJ7wNY1T74dg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-ktVLuBkI6QVOm5BwO/WbdGwxgeetAMJa7TTmR8qBarXF0OU2NKjvjUtPJAl2y8t+zBRczJl/1VOl9gua6WcK2g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-SGhlQ8bDjL1Cz2KnsKMasr/5sTcwG/SZkB6WCJxLsmSm/3aS2C+3p39bA7iZ2/94+NkVDySZfbiGoaSZSFHYxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -4649,6 +4917,15 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xterm/addon-fit": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz", @@ -4664,6 +4941,15 @@ "addons/*" ] }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4689,6 +4975,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/aria-hidden": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", @@ -4732,6 +5027,26 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.25", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.25.tgz", @@ -4755,6 +5070,12 @@ "require-from-string": "^2.0.2" } }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "license": "MIT" + }, "node_modules/browserslist": { "version": "4.28.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", @@ -4820,6 +5141,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -4891,6 +5225,15 @@ "node": ">=6" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -4917,6 +5260,12 @@ "dev": true, "license": "MIT" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/cose-base": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", @@ -4926,6 +5275,18 @@ "layout-base": "^1.0.0" } }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/css-tree": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", @@ -5557,6 +5918,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/dingbat-to-unicode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", + "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==", + "license": "BSD-2-Clause" + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", @@ -5574,6 +5941,15 @@ "@types/trusted-types": "^2.0.7" } }, + "node_modules/duck": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz", + "integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==", + "license": "BSD", + "dependencies": { + "underscore": "^1.13.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.349", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz", @@ -5740,6 +6116,15 @@ } } }, + "node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -6177,6 +6562,12 @@ "node": ">=0.10.0" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/import-meta-resolve": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", @@ -6187,6 +6578,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/inline-style-parser": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", @@ -6265,6 +6662,12 @@ "dev": true, "license": "MIT" }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -6358,6 +6761,18 @@ "node": ">=6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/katex": { "version": "0.16.47", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", @@ -6385,6 +6800,15 @@ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", "license": "MIT" }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -6662,6 +7086,17 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/lop": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/lop/-/lop-0.4.2.tgz", + "integrity": "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==", + "license": "BSD-2-Clause", + "dependencies": { + "duck": "^0.1.12", + "option": "~0.2.1", + "underscore": "^1.13.1" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6701,6 +7136,30 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/mammoth": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.12.0.tgz", + "integrity": "sha512-cwnK1RIcRdDMi2HRx2EXGYlxqIEh0Oo3bLhorgnsVJi2UkbX1+jKxuBNR9PC5+JaX7EkmJxFPmo6mjLpqShI2w==", + "license": "BSD-2-Clause", + "dependencies": { + "@xmldom/xmldom": "^0.8.6", + "argparse": "~1.0.3", + "base64-js": "^1.5.1", + "bluebird": "~3.4.0", + "dingbat-to-unicode": "^1.0.1", + "jszip": "^3.7.1", + "lop": "^0.4.2", + "path-is-absolute": "^1.0.0", + "underscore": "^1.13.1", + "xmlbuilder": "^10.0.0" + }, + "bin": { + "mammoth": "bin/mammoth" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -7846,12 +8305,24 @@ "regex-recursion": "^6.0.2" } }, + "node_modules/option": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz", + "integrity": "sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==", + "license": "BSD-2-Clause" + }, "node_modules/package-manager-detector": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.7.0.tgz", "integrity": "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==", "license": "MIT" }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -7896,6 +8367,15 @@ "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", "license": "MIT" }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -7903,6 +8383,18 @@ "dev": true, "license": "MIT" }, + "node_modules/pdfjs-dist": { + "version": "6.2.108", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-6.2.108.tgz", + "integrity": "sha512-YxFb+SQcodN2rnX9Tn3dHYlqfb7NjlzzfONPpJd+AKoKtUjEdevTfbC07d5TcczzOK6261auRkP/M8OBHs9vFQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=22.13.0 || >=24" + }, + "optionalDependencies": { + "@napi-rs/canvas": "^1.0.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -7981,6 +8473,12 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -8268,6 +8766,21 @@ } } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", @@ -8559,6 +9072,12 @@ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", "license": "BSD-3-Clause" }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -8594,6 +9113,12 @@ "semver": "bin/semver.js" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/shiki": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.0.2.tgz", @@ -8649,6 +9174,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "license": "Apache-2.0", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -8709,6 +9252,15 @@ "node": ">= 20" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -8930,6 +9482,12 @@ "node": ">=14.17" } }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "license": "MIT" + }, "node_modules/undici": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz", @@ -9138,6 +9696,12 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/uuid": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", @@ -9441,6 +10005,45 @@ "node": ">=8" } }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "license": "Apache-2.0", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -9451,6 +10054,15 @@ "node": ">=18" } }, + "node_modules/xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 5598997..856554a 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,10 @@ "clsx": "^2.1.1", "i18next": "^26.0.8", "lucide-react": "^1.14.0", + "mammoth": "^1.12.0", "monaco-editor": "^0.55.1", "next-themes": "^0.4.6", + "pdfjs-dist": "^6.2.108", "radix-ui": "^1.4.3", "react": "^19", "react-dom": "^19", @@ -49,6 +51,7 @@ "streamdown": "^2.5.0", "tailwind-merge": "^3.5.0", "tailwindcss": "^4.2.4", + "xlsx": "^0.18.5", "zustand": "^5.0.12" }, "devDependencies": { diff --git a/src/components/chat/message/MessageItem.tsx b/src/components/chat/message/MessageItem.tsx index 03eae9b..1226351 100644 --- a/src/components/chat/message/MessageItem.tsx +++ b/src/components/chat/message/MessageItem.tsx @@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next"; import { Check, Copy, RefreshCw, AlertTriangle } from "lucide-react"; import { cn } from "@/lib/utils"; import type { Message, TokenUsage } from "@/lib/ipc"; +import { MessageContentBlocks } from "@/features/chat-content/MessageContentBlocks"; import { MessageResponse } from "../markdown/MessageResponse"; import { ThinkingBlock } from "./ThinkingBlock"; import { ToolActionsGroup } from "./ToolActionsGroup"; @@ -189,7 +190,11 @@ function MessageBubble({ ))} ) : null} - + {message.blocks && message.blocks.length > 0 && !isStreaming ? ( + + ) : ( + + )} ); } diff --git a/src/features/chat-content/MessageContentBlocks.tsx b/src/features/chat-content/MessageContentBlocks.tsx new file mode 100644 index 0000000..e054e10 --- /dev/null +++ b/src/features/chat-content/MessageContentBlocks.tsx @@ -0,0 +1,53 @@ +import { Component, type ErrorInfo, type ReactNode } from "react"; +import { useTranslation } from "react-i18next"; +import type { ContentBlock } from "@/lib/ipc"; +import { resolveBlockRenderer } from "./renderer-registry"; + +interface MessageContentBlocksProps { + blocks: ContentBlock[]; + sessionId: string; + isStreaming: boolean; +} + +export function MessageContentBlocks({ blocks, sessionId, isStreaming }: MessageContentBlocksProps) { + return ( +
+ {[...blocks] + .sort((left, right) => left.position - right.position || left.id.localeCompare(right.id)) + .map((block) => { + const Renderer = resolveBlockRenderer(block.kind); + return ( + + + + ); + })} +
+ ); +} + +class BlockErrorBoundary extends Component<{ children: ReactNode }, { failed: boolean }> { + public state = { failed: false }; + + public static getDerivedStateFromError() { + return { failed: true }; + } + + public componentDidCatch(_error: Error, _info: ErrorInfo) { + // A block failure must not prevent adjacent Markdown/tool blocks from rendering. + } + + public render() { + if (this.state.failed) return ; + return this.props.children; + } +} + +function BlockRenderFailure() { + const { t } = useTranslation("chat"); + return ( +

+ {t("richContent.blockUnavailable")} +

+ ); +} diff --git a/src/features/chat-content/RichContentCard.tsx b/src/features/chat-content/RichContentCard.tsx new file mode 100644 index 0000000..dd2c2bf --- /dev/null +++ b/src/features/chat-content/RichContentCard.tsx @@ -0,0 +1,49 @@ +import type { ReactNode } from "react"; +import { LoaderCircle } from "lucide-react"; +import { cn } from "@/lib/utils"; + +interface RichContentCardProps { + title: string; + icon: ReactNode; + status?: "pending" | "failed" | "unsupported" | "ready"; + actions?: ReactNode; + children: ReactNode; + footer?: ReactNode; + className?: string; +} + +export function RichContentCard({ + title, + icon, + status = "ready", + actions, + children, + footer, + className, +}: RichContentCardProps) { + return ( +
+
+ + {icon} + +

{title}

+ {status === "pending" ? ( + + ) : null} + {actions ?
{actions}
: null} +
+
{children}
+ {footer ? ( +
{footer}
+ ) : null} +
+ ); +} diff --git a/src/features/chat-content/renderer-registry.tsx b/src/features/chat-content/renderer-registry.tsx new file mode 100644 index 0000000..6e40193 --- /dev/null +++ b/src/features/chat-content/renderer-registry.tsx @@ -0,0 +1,29 @@ +import type { ComponentType } from "react"; +import type { ContentBlock } from "@/lib/ipc"; + +import { ArtifactBlockRenderer } from "./renderers/ArtifactBlockRenderer"; +import { ImageBlockRenderer } from "./renderers/ImageBlockRenderer"; +import { MarkdownBlockRenderer } from "./renderers/MarkdownBlockRenderer"; +import { NoticeBlockRenderer } from "./renderers/NoticeBlockRenderer"; + +export interface BlockRendererProps { + block: ContentBlock; + sessionId: string; + isStreaming: boolean; +} + +const REGISTRY: Record> = { + markdown: MarkdownBlockRenderer, + // Chart and map blocks are deliberately non-executing until their own + // renderer phases complete; their persisted fallback remains readable. + chart: NoticeBlockRenderer, + map: NoticeBlockRenderer, + artifact: ArtifactBlockRenderer, + image: ImageBlockRenderer, + notice: NoticeBlockRenderer, + unknown: NoticeBlockRenderer, +}; + +export function resolveBlockRenderer(kind: ContentBlock["kind"]): ComponentType { + return REGISTRY[kind] ?? NoticeBlockRenderer; +} diff --git a/src/features/chat-content/renderers/ArtifactBlockRenderer.tsx b/src/features/chat-content/renderers/ArtifactBlockRenderer.tsx new file mode 100644 index 0000000..e151e95 --- /dev/null +++ b/src/features/chat-content/renderers/ArtifactBlockRenderer.tsx @@ -0,0 +1,81 @@ +import { useCallback, useEffect, useState } from "react"; +import { Download, FileText, Eye, LoaderCircle } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/ui/button"; +import { artifactsIpc, type ArtifactMetadata, type ArtifactPreview } from "@/lib/ipc"; +import type { BlockRendererProps } from "../renderer-registry"; +import { RichContentCard } from "../RichContentCard"; +import { readArtifactPayload } from "../types"; +import { NoticeBlockRenderer } from "./NoticeBlockRenderer"; +import { ArtifactPreviewDialog } from "./ArtifactPreviewDialog"; + +export function ArtifactBlockRenderer({ block, sessionId }: BlockRendererProps) { + const { t } = useTranslation("chat"); + const payload = readArtifactPayload(block); + const [metadata, setMetadata] = useState(null); + const [preview, setPreview] = useState(null); + const [open, setOpen] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + if (!payload) return; + let active = true; + artifactsIpc.getMetadata(sessionId, payload.artifact_id).then((result) => active && setMetadata(result)).catch(() => active && setError(t("richContent.artifact.unavailable"))); + return () => { active = false; }; + }, [payload?.artifact_id, sessionId, t]); + + const exportArtifact = useCallback(async () => { + if (!metadata) return; + try { + const result = await artifactsIpc.export(sessionId, metadata.artifact_id); + if (result.status === "saved") setError(null); + } catch { + setError(t("richContent.artifact.exportFailed")); + } + }, [metadata, sessionId, t]); + + const openPreview = useCallback(async () => { + if (!metadata) return; + setLoading(true); + setError(null); + try { + const result = await artifactsIpc.getPreview(sessionId, metadata.artifact_id); + setPreview(result); + setOpen(true); + } catch { + setError(t("richContent.preview.failed")); + } finally { + setLoading(false); + } + }, [metadata, sessionId, t]); + + if (!payload) return ; + const title = metadata?.display_name ?? payload.display_name ?? t("richContent.artifact.untitled"); + return ( + <> + } + status={block.status} + actions={loading ? : null} + footer={error ? {error} : metadata ? `${metadata.media_type} · ${formatBytes(metadata.byte_size)} · ${t(`richContent.origin.${metadata.origin_kind}`)} · ${formatCreatedAt(metadata.created_at)}` : t("richContent.artifact.loading")} + > +
+ + +
+
+ {metadata ? : null} + + ); +} + +function formatBytes(value: number): string { + return new Intl.NumberFormat(undefined, { style: "unit", unit: "byte", unitDisplay: "narrow", notation: "compact" }).format(value); +} + +function formatCreatedAt(value: string): string { + const date = new Date(value); + return Number.isNaN(date.valueOf()) ? "—" : new Intl.DateTimeFormat(undefined, { dateStyle: "short", timeStyle: "short" }).format(date); +} diff --git a/src/features/chat-content/renderers/ArtifactPreviewDialog.tsx b/src/features/chat-content/renderers/ArtifactPreviewDialog.tsx new file mode 100644 index 0000000..b521ed3 --- /dev/null +++ b/src/features/chat-content/renderers/ArtifactPreviewDialog.tsx @@ -0,0 +1,301 @@ +import { useEffect, useRef, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { LoaderCircle } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import { artifactsIpc, type ArtifactMetadata, type ArtifactPreview } from "@/lib/ipc"; + +interface ArtifactPreviewDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + sessionId: string; + metadata: ArtifactMetadata; + preview: ArtifactPreview | null; + onExport: () => void; +} + +export function ArtifactPreviewDialog({ + open, + onOpenChange, + sessionId, + metadata, + preview, + onExport, +}: ArtifactPreviewDialogProps) { + const { t } = useTranslation("chat"); + const [base64, setBase64] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + if (!open || !preview || preview.kind === "text" || preview.kind === "csv" || preview.kind === "download_only") { + return; + } + let active = true; + setBase64(null); + setError(null); + artifactsIpc + .readPreviewBase64(sessionId, metadata.artifact_id) + .then((value) => active && setBase64(value)) + .catch(() => active && setError(t("richContent.preview.failed"))); + return () => { + active = false; + }; + }, [metadata.artifact_id, open, preview, sessionId, t]); + + return ( + + + + {metadata.display_name} + + {metadata.media_type} · {formatBytes(metadata.byte_size)} + + +
+ {preview?.kind === "text" ? ( + + ) : preview?.kind === "csv" ? ( + + ) : error ? ( +

{error}

+ ) : base64 ? ( + + ) : preview?.kind === "download_only" ? ( +

{t("richContent.preview.downloadOnly")}

+ ) : ( +
+ + {t("richContent.preview.loading")} +
+ )} +
+ +

{t("richContent.preview.readOnly")}

+ +
+
+
+ ); +} + +function BinaryPreview({ kind, base64, mediaType }: { kind: ArtifactPreview["kind"] | undefined; base64: string; mediaType: string }) { + if (kind === "image") return ; + if (kind === "pdf") return ; + if (kind === "spreadsheet") return ; + if (kind === "document") return ; + return null; +} + +function TextPreview({ text, truncated }: { text: string; truncated: boolean }) { + const { t } = useTranslation("chat"); + return ( +
+ {truncated ?

{t("richContent.preview.truncated")}

: null} +
{text}
+
+ ); +} + +function CsvPreview({ text, truncated }: { text: string; truncated: boolean }) { + const { t } = useTranslation("chat"); + const rows = parseCsv(text).slice(0, 200).map((row) => row.slice(0, 50)); + return ( +
+ {truncated ?

{t("richContent.preview.truncated")}

: null} +
+ + + {rows.map((row, rowIndex) => ( + + {row.map((cell, cellIndex) => ( + + ))} + + ))} + +
{cell}
+
+
+ ); +} + +function ImagePreview({ base64, mediaType }: { base64: string; mediaType: string }) { + const [zoom, setZoom] = useState(1); + const { t } = useTranslation("chat"); + const source = `data:${mediaType};base64,${base64}`; + return ( +
+
+ {t("richContent.image.previewAlt")} +
+
+ + + +
+
+ ); +} + +function PdfPreview({ base64 }: { base64: string }) { + const canvasRef = useRef(null); + const [error, setError] = useState(false); + const [pageNumber, setPageNumber] = useState(1); + const [pageCount, setPageCount] = useState(null); + useEffect(() => { + let cancelled = false; + const task = (async () => { + try { + const pdfjs = await import("pdfjs-dist"); + pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString(); + const document = await pdfjs.getDocument({ data: base64ToBytes(base64) }).promise; + if (document.numPages > 200) throw new Error("PDF page limit exceeded"); + if (!cancelled) setPageCount(document.numPages); + const page = await document.getPage(Math.min(pageNumber, document.numPages)); + const viewport = page.getViewport({ scale: 1.25 }); + const canvas = canvasRef.current; + if (!canvas || cancelled) return; + canvas.width = Math.ceil(viewport.width); + canvas.height = Math.ceil(viewport.height); + const context = canvas.getContext("2d"); + if (!context) throw new Error("2D canvas unavailable"); + await page.render({ canvas, canvasContext: context, viewport }).promise; + } catch { + if (!cancelled) setError(true); + } + })(); + void task; + return () => { cancelled = true; }; + }, [base64, pageNumber]); + const { t } = useTranslation("chat"); + if (error) return

{t("richContent.preview.failed")}

; + return ( +
+
+ {pageCount && pageCount > 1 ? ( +
+ + {t("richContent.preview.page", { current: pageNumber, total: pageCount })} + +
+ ) : null} +
+ ); +} + +function SpreadsheetPreview({ base64 }: { base64: string }) { + const [sheets, setSheets] = useState | null>(null); + const [activeSheet, setActiveSheet] = useState(0); + const [error, setError] = useState(false); + useEffect(() => { + let active = true; + void import("xlsx") + .then((xlsx) => { + const workbook = xlsx.read(base64ToBytes(base64), { type: "array", dense: false }); + const nextSheets = workbook.SheetNames.slice(0, 12).flatMap((name) => { + const sheet = workbook.Sheets[name]; + if (!sheet) return []; + const rows = xlsx.utils.sheet_to_json(sheet, { header: 1, raw: true, defval: "" }) + .slice(0, 200) + .map((row) => row.slice(0, 50)); + return [{ name, rows }]; + }); + if (active) { + setActiveSheet(0); + setSheets(nextSheets); + } + }) + .catch(() => active && setError(true)); + return () => { active = false; }; + }, [base64]); + const { t } = useTranslation("chat"); + if (error) return

{t("richContent.preview.failed")}

; + if (!sheets) return ; + const sheet = sheets[activeSheet]; + if (!sheet) return

{t("richContent.preview.failed")}

; + return ( +
+
+ {sheets.map((item, index) => ( + + ))} +
+
{sheet.rows.map((row, rowIndex) => {row.map((cell, cellIndex) => )})}
{String(cell)}
+
+ ); +} + +function DocumentPreview({ base64 }: { base64: string }) { + const [text, setText] = useState(null); + const [error, setError] = useState(false); + useEffect(() => { + let active = true; + void import("mammoth/mammoth.browser") + .then(async (mammoth) => { + const result = await mammoth.convertToHtml({ arrayBuffer: base64ToArrayBuffer(base64) }); + const parsed = new DOMParser().parseFromString(result.value, "text/html"); + if (active) setText((parsed.body.textContent ?? "").slice(0, 512_000)); + }) + .catch(() => active && setError(true)); + return () => { active = false; }; + }, [base64]); + const { t } = useTranslation("chat"); + if (error) return

{t("richContent.preview.failed")}

; + if (text === null) return ; + return
{text}
; +} + +function PreviewLoader() { + const { t } = useTranslation("chat"); + return
{t("richContent.preview.loading")}
; +} + +function base64ToBytes(value: string): Uint8Array { + const binary = window.atob(value); + const bytes = new Uint8Array(binary.length); + for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index); + return bytes; +} + +function base64ToArrayBuffer(value: string): ArrayBuffer { + const bytes = base64ToBytes(value); + return new Uint8Array(bytes).buffer; +} + +function parseCsv(text: string): string[][] { + const rows: string[][] = [[]]; + let value = ""; + let quoted = false; + for (let index = 0; index < text.length; index += 1) { + const character = text[index]; + if (character === '"' && text[index + 1] === '"' && quoted) { + value += '"'; + index += 1; + } else if (character === '"') { + quoted = !quoted; + } else if (character === "," && !quoted) { + rows[rows.length - 1].push(value); + value = ""; + } else if ((character === "\n" || character === "\r") && !quoted) { + if (character === "\r" && text[index + 1] === "\n") index += 1; + rows[rows.length - 1].push(value); + rows.push([]); + value = ""; + } else { + value += character; + } + } + rows[rows.length - 1].push(value); + return rows.filter((row) => row.length > 1 || row[0] !== ""); +} + +function formatBytes(value: number): string { + return new Intl.NumberFormat(undefined, { style: "unit", unit: "byte", unitDisplay: "narrow", notation: "compact" }).format(value); +} diff --git a/src/features/chat-content/renderers/ImageBlockRenderer.tsx b/src/features/chat-content/renderers/ImageBlockRenderer.tsx new file mode 100644 index 0000000..1ba6ec1 --- /dev/null +++ b/src/features/chat-content/renderers/ImageBlockRenderer.tsx @@ -0,0 +1,46 @@ +import { useEffect, useState } from "react"; +import { Image as ImageIcon, LoaderCircle } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { artifactsIpc, type ArtifactMetadata } from "@/lib/ipc"; +import type { BlockRendererProps } from "../renderer-registry"; +import { RichContentCard } from "../RichContentCard"; +import { readArtifactPayload } from "../types"; +import { NoticeBlockRenderer } from "./NoticeBlockRenderer"; +import { ArtifactPreviewDialog } from "./ArtifactPreviewDialog"; + +export function ImageBlockRenderer({ block, sessionId }: BlockRendererProps) { + const { t } = useTranslation("chat"); + const payload = readArtifactPayload(block); + const [metadata, setMetadata] = useState(null); + const [base64, setBase64] = useState(null); + const [error, setError] = useState(null); + const [open, setOpen] = useState(false); + useEffect(() => { + if (!payload) return; + let active = true; + void Promise.all([ + artifactsIpc.getMetadata(sessionId, payload.artifact_id), + artifactsIpc.readPreviewBase64(sessionId, payload.artifact_id), + ]).then(([nextMetadata, nextBase64]) => { + if (!active) return; + setMetadata(nextMetadata); + setBase64(nextBase64); + }).catch(() => active && setError(t("richContent.artifact.unavailable"))); + return () => { active = false; }; + }, [payload?.artifact_id, sessionId, t]); + if (!payload) return ; + return ( + <> + } status={block.status} footer={error ? {error} : metadata ? `${metadata.media_type} · ${formatBytes(metadata.byte_size)}${payload.width && payload.height ? ` · ${payload.width} × ${payload.height}` : ""}` : t("richContent.artifact.loading")}> +
+ {base64 && metadata ? : error ?

{error}

: } +
+
+ {metadata ? void artifactsIpc.export(sessionId, metadata.artifact_id)} /> : null} + + ); +} + +function formatBytes(value: number): string { + return new Intl.NumberFormat(undefined, { style: "unit", unit: "byte", unitDisplay: "narrow", notation: "compact" }).format(value); +} diff --git a/src/features/chat-content/renderers/MarkdownBlockRenderer.tsx b/src/features/chat-content/renderers/MarkdownBlockRenderer.tsx new file mode 100644 index 0000000..22b3ff8 --- /dev/null +++ b/src/features/chat-content/renderers/MarkdownBlockRenderer.tsx @@ -0,0 +1,10 @@ +import { MessageResponse } from "@/components/chat/markdown/MessageResponse"; +import type { BlockRendererProps } from "../renderer-registry"; +import { readMarkdownPayload } from "../types"; +import { NoticeBlockRenderer } from "./NoticeBlockRenderer"; + +export function MarkdownBlockRenderer({ block, isStreaming, sessionId }: BlockRendererProps) { + const payload = readMarkdownPayload(block); + if (!payload) return ; + return ; +} diff --git a/src/features/chat-content/renderers/NoticeBlockRenderer.tsx b/src/features/chat-content/renderers/NoticeBlockRenderer.tsx new file mode 100644 index 0000000..5eae6b9 --- /dev/null +++ b/src/features/chat-content/renderers/NoticeBlockRenderer.tsx @@ -0,0 +1,25 @@ +import { AlertTriangle, CircleAlert, Info } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import type { BlockRendererProps } from "../renderer-registry"; +import { readNoticePayload } from "../types"; + +export function NoticeBlockRenderer({ block }: BlockRendererProps) { + const { t } = useTranslation("chat"); + const payload = readNoticePayload(block); + const severity = payload?.severity ?? (block.status === "failed" ? "error" : "info"); + const Icon = severity === "error" ? AlertTriangle : severity === "warning" ? CircleAlert : Info; + const message = payload ? t(payload.message_key, payload.params) : t(block.fallback.message_key || "richContent.blockUnavailable", block.fallback.params); + return ( +
+ + {message} +
+ ); +} diff --git a/src/features/chat-content/types.ts b/src/features/chat-content/types.ts new file mode 100644 index 0000000..a5426ef --- /dev/null +++ b/src/features/chat-content/types.ts @@ -0,0 +1,61 @@ +import type { ContentBlock } from "@/lib/ipc"; + +export interface ArtifactBlockPayload { + artifact_id: string; + display_name?: string; + preview_hint?: string; + alt?: string; + width?: number; + height?: number; +} + +export interface MarkdownBlockPayload { + text: string; +} + +export interface NoticeBlockPayload { + message_key: string; + severity?: "info" | "warning" | "error"; + params?: Record; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function isString(value: unknown): value is string { + return typeof value === "string"; +} + +export function readMarkdownPayload(block: ContentBlock): MarkdownBlockPayload | null { + if (!isRecord(block.payload) || !isString(block.payload.text)) return null; + return { text: block.payload.text }; +} + +export function readArtifactPayload(block: ContentBlock): ArtifactBlockPayload | null { + if (!isRecord(block.payload) || !isString(block.payload.artifact_id)) return null; + return { + artifact_id: block.payload.artifact_id, + display_name: isString(block.payload.display_name) ? block.payload.display_name : undefined, + preview_hint: isString(block.payload.preview_hint) ? block.payload.preview_hint : undefined, + alt: isString(block.payload.alt) ? block.payload.alt : undefined, + width: typeof block.payload.width === "number" ? block.payload.width : undefined, + height: typeof block.payload.height === "number" ? block.payload.height : undefined, + }; +} + +export function readNoticePayload(block: ContentBlock): NoticeBlockPayload | null { + if (!isRecord(block.payload) || !isString(block.payload.message_key)) return null; + const severity = block.payload.severity; + const params = isRecord(block.payload.params) + ? Object.entries(block.payload.params).reduce>((result, [key, value]) => { + if (isString(value)) result[key] = value; + return result; + }, {}) + : undefined; + return { + message_key: block.payload.message_key, + severity: severity === "warning" || severity === "error" ? severity : "info", + params, + }; +} diff --git a/src/locales/en/chat.json b/src/locales/en/chat.json index b59cc1b..03f5de3 100644 --- a/src/locales/en/chat.json +++ b/src/locales/en/chat.json @@ -108,5 +108,68 @@ }, "toolLogs": { "empty": "No tool calls yet" + }, + "richContent": { + "blockUnavailable": "This rich result is unavailable. Its fallback content is still available.", + "download": "Download", + "artifact": { + "untitled": "Untitled artifact", + "loading": "Loading artifact…", + "unavailable": "Artifact is unavailable.", + "exportFailed": "Couldn't export the artifact." + }, + "origin": { + "model": "Model", + "agent": "Agent", + "mcp": "MCP", + "skill": "Skill", + "user": "User", + "preview": "Preview" + }, + "preview": { + "open": "Preview", + "loading": "Loading preview…", + "failed": "The preview couldn't be loaded.", + "downloadOnly": "This file can only be downloaded.", + "readOnly": "Preview is read-only.", + "truncated": "Preview is truncated for safety.", + "pdfPage": "PDF page preview", + "previousPage": "Previous", + "nextPage": "Next", + "page": "Page {{current}} of {{total}}" + }, + "image": { + "untitled": "Untitled image", + "open": "Open image preview", + "previewAlt": "Image preview", + "zoomOut": "Zoom out", + "fit": "Fit", + "zoomIn": "Zoom in" + }, + "chart": { + "toggleData": "Show or hide chart data", + "exportCsv": "Export CSV", + "exportFailed": "Couldn't export chart data.", + "localOnly": "Rendered from local, validated data.", + "fallbackData": "Chart unavailable; showing data instead.", + "visualization": "Chart visualization", + "metric": "Metric", + "series": "Series", + "x": "X", + "y": "Y" + }, + "map": { + "copyCoordinates": "Copy GeoJSON", + "toggleFeatures": "Show or hide map features", + "exportGeojson": "Export GeoJSON", + "copyFailed": "Couldn't copy the GeoJSON.", + "exportFailed": "Couldn't export the GeoJSON.", + "copied": "GeoJSON copied.", + "localOnly": "Rendered without remote map tiles.", + "fallbackFeatures": "Map unavailable; showing features instead.", + "visualization": "Map visualization", + "featureCount_one": "{{count}} feature", + "featureCount_other": "{{count}} features" + } } } diff --git a/src/locales/zh-CN/chat.json b/src/locales/zh-CN/chat.json index 1a4b68b..a0af1c6 100644 --- a/src/locales/zh-CN/chat.json +++ b/src/locales/zh-CN/chat.json @@ -108,5 +108,68 @@ }, "toolLogs": { "empty": "暂无工具调用" + }, + "richContent": { + "blockUnavailable": "此富内容结果暂不可用,仍可查看其降级内容。", + "download": "下载", + "artifact": { + "untitled": "未命名产物", + "loading": "正在加载产物…", + "unavailable": "产物不可用。", + "exportFailed": "无法导出该产物。" + }, + "origin": { + "model": "模型", + "agent": "智能体", + "mcp": "MCP", + "skill": "技能", + "user": "用户", + "preview": "预览" + }, + "preview": { + "open": "预览", + "loading": "正在加载预览…", + "failed": "无法加载预览。", + "downloadOnly": "此文件仅支持下载。", + "readOnly": "预览为只读。", + "truncated": "为安全起见,预览已截断。", + "pdfPage": "PDF 页面预览", + "previousPage": "上一页", + "nextPage": "下一页", + "page": "第 {{current}} / {{total}} 页" + }, + "image": { + "untitled": "未命名图片", + "open": "打开图片预览", + "previewAlt": "图片预览", + "zoomOut": "缩小", + "fit": "适应窗口", + "zoomIn": "放大" + }, + "chart": { + "toggleData": "显示或隐藏图表数据", + "exportCsv": "导出 CSV", + "exportFailed": "无法导出图表数据。", + "localOnly": "由本地验证后的数据渲染。", + "fallbackData": "图表不可用,正在显示数据。", + "visualization": "图表可视化", + "metric": "指标", + "series": "序列", + "x": "X", + "y": "Y" + }, + "map": { + "copyCoordinates": "复制 GeoJSON", + "toggleFeatures": "显示或隐藏地图要素", + "exportGeojson": "导出 GeoJSON", + "copyFailed": "无法复制 GeoJSON。", + "exportFailed": "无法导出 GeoJSON。", + "copied": "已复制 GeoJSON。", + "localOnly": "未加载远程底图。", + "fallbackFeatures": "地图不可用,正在显示要素。", + "visualization": "地图可视化", + "featureCount_one": "{{count}} 个要素", + "featureCount_other": "{{count}} 个要素" + } } } diff --git a/src/types/mammoth.browser.d.ts b/src/types/mammoth.browser.d.ts new file mode 100644 index 0000000..999e5e9 --- /dev/null +++ b/src/types/mammoth.browser.d.ts @@ -0,0 +1,3 @@ +declare module "mammoth/mammoth.browser" { + export function convertToHtml(input: { arrayBuffer: ArrayBuffer }): Promise<{ value: string }>; +} From ecc7f89d76ec2591e2ff20d21da03d84df4e4316 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 08:38:32 +0800 Subject: [PATCH 12/16] feat(rich-content): complete r3 chart renderer --- .../06-implementation-log.md | 25 ++- package-lock.json | 32 +++ package.json | 1 + src-tauri/build.rs | 1 + src-tauri/gen/schemas/acl-manifests.json | 2 +- src-tauri/gen/schemas/desktop-schema.json | 12 ++ src-tauri/gen/schemas/windows-schema.json | 12 ++ src-tauri/permissions/main.toml | 1 + src-tauri/src/commands/chart.rs | 104 ++++++++++ src-tauri/src/commands/mod.rs | 1 + src-tauri/src/lib.rs | 1 + .../renderers/ChartBlockRenderer.tsx | 184 ++++++++++++++++++ .../chat-content/renderers/chart-types.ts | 94 +++++++++ src/lib/ipc/artifacts.ts | 2 + 14 files changed, 465 insertions(+), 7 deletions(-) create mode 100644 src-tauri/src/commands/chart.rs create mode 100644 src/features/chat-content/renderers/ChartBlockRenderer.tsx create mode 100644 src/features/chat-content/renderers/chart-types.ts diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index eb6c93d..d1572a5 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0、R1 已通过远程全量 CI。R2 文件预览已完成本地验证,待阶段提交、推送与远程 CI;R3–R4 尚未开始阶段提交。 +> **状态:** R0、R1、R2 已通过远程全量 CI。R3 图表已完成本地验证,待阶段提交、推送与远程 CI;R4 尚未开始阶段提交。 --- @@ -22,8 +22,8 @@ |---|---|---|---|---|---| | R0 契约/安全基线 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `b1ed884`;[CI #31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 的 8 项检查全绿 | | R1 ArtifactService/图片/下载 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `53a079d`;[CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 8 项检查全绿 | -| R2 文件预览 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 惰性只读预览、图片 Dialog 与下载回退;待 commit/push/CI | -| R3 图表 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送 | +| R2 文件预览 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `2e979e1`;[CI #31285793427](https://github.com/knqiufan/MisakaX/actions/runs/31285793427) 的 8 项检查全绿 | +| R3 图表 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限 ChartSpec、ECharts richText、可访问数据表和 ArtifactService CSV 导出;待 commit/push/CI | | R4 地图 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送;R4b 不在范围内 | | R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | | R6 加固/发布 | 未开始 | 待分配 | — | — | 三平台/沙箱 gate;通过阶段门禁后完成 | @@ -160,11 +160,24 @@ - **代码审查:** 确认 Renderer Registry 对 chart/map 仍映射到非执行 notice;文件 bytes 只能经 artifact 窄 IPC 获取,未接受路径、`file:`、HTML、SVG 或远端 URL;DOCX 仅抽取 DOM `textContent`,不注入转换出的 HTML。每个块由 ErrorBoundary 隔离,图片/文档失败不会中断相邻 Markdown。发现阶段拆分后未提交的 R3/R4 renderer 仍需其导出 IPC 类型,已保留在未暂存候选切片中,未混入 R2。 - **验证:** `npm run build` → pass(Vite 提示部分动态依赖 chunk 大于 500 kB,未阻塞);`npm test -- --run` → 38 files / 271 passed。Vitest/JSDOM 输出 `HTMLCanvasElement.getContext` 未实现诊断,但测试进程 exit 0。 - **未验证:** 未执行三平台人工 PDF/XLSX/DOCX/图片预览、恶意加密 Office/压缩炸弹压测或屏幕阅读器实测;不把这些未执行项当作通过。R3/R4 renderer 尚未进行阶段审查、提交或推送。 -- **Git:** 待提交;暂存范围仅限 R2 UI、预览依赖、i18n、设计规范与本记录。 -- **远程 CI:** 待 R2 commit 推送后运行。 +- **Git:** `2e979e1`(`feat(rich-content): complete r2 file previews`)已非强制推送至 `origin/codex/rich-content-r0-r4`。 +- **远程 CI:** [CI #31285793427](https://github.com/knqiufan/MisakaX/actions/runs/31285793427) completed/success;Rust、Frontend、三平台 Terminal Runtime 与三平台 Tauri Build 共 8 项检查全绿。 - **风险/回滚:** 移除 R2 renderer/依赖即可恢复 R1 的后端 artifact 能力;关闭 `MISAKAX_RICH_CONTENT_RENDER` 继续显示 legacy Markdown。预览始终为只读,任何失败保留下载路径。 - **文档同步:** `docs/design/frontend-ui-guidelines.md` §4.6.x.1;本实施记录。 -- **下一步:** 审查暂存差异、提交 R2 并等待 remote CI 全绿;随后才能开始 R3。 +- **下一步:** R2 已完成;可开始 R3 的独立阶段审查与实现收口。 + +### 2026-08-09 — R3:受限图表、数据表与 CSV 导出 + +- **范围:** 启用 `chart` 块的前端 renderer,动态加载 ECharts,提供 metric/data-table fallback、ARIA 标注和通过 ArtifactService 的 CSV 导出。地图保持未注册 fallback,未纳入本阶段。 +- **修改:** 新增前端 ChartSpec reader(24 series、5000 points、512 字符标签上限)和 `ChartBlockRenderer`;新增 `chart_export_csv` Rust command、AppManifest/最小权限/schema 同步与窄 IPC。CSV 逐字段转义,且为 `= + - @` 前缀加 apostrophe,避免表格公式注入;导出前验证消息归属当前会话。 +- **代码审查:** ChartSpec 仅映射固定图类型,未接收原始 ECharts option/HTML/function/外部 URL;ECharts tooltip 固定为 `richText`,不使用 HTML renderer;加载失败降级到同一份数据表,`role="img"`/ARIA 与键盘可达的数据表操作并存。未发现会扩大 CSP、FS/HTTP/Shell capability 的变更。 +- **验证:** `cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass;`cargo test --all-features --lib chart` → 2 passed / 0 failed;`cargo test --all-features --test security_config_baseline_tests` → 5 passed / 0 failed;`npm run build` → pass(动态 chunk 大小 warning);`npm test -- --run` → 38 files / 271 passed(JSDOM canvas diagnostic,exit 0)。 +- **未验证:** 未进行真实屏幕阅读器、手工深浅主题/窗口缩放或大量 series 的交互回归;R4 地图代码、MapLibre 依赖和 GeoJSON 导出未纳入暂存。 +- **Git:** 待提交;暂存范围为 R3 图表、CSV 导出、受控命令权限、ECharts 依赖与本记录。 +- **远程 CI:** 待 R3 commit 推送后运行。 +- **风险/回滚:** 回滚本阶段可恢复 chart→notice fallback;CSV 导出临时 artifact 会在客户端导出流程完成后 expire,不产生通用文件写入权限。 +- **文档同步:** R2 已同步的 `frontend-ui-guidelines.md` §4.6.x.1 对图表的通用规范继续适用;本实施记录补充实现证据。 +- **下一步:** 审查 R3 暂存差异、提交并等待 remote CI 全绿;之后才开始 R4。 ## 后续记录模板 diff --git a/package-lock.json b/package-lock.json index 4e3052b..d2c7c9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@xterm/xterm": "6.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "echarts": "^6.1.0", "i18next": "^26.0.8", "lucide-react": "^1.14.0", "mammoth": "^1.12.0", @@ -5950,6 +5951,22 @@ "underscore": "^1.13.1" } }, + "node_modules/echarts": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.1.0.tgz", + "integrity": "sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.1.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/electron-to-chromium": { "version": "1.5.349", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.349.tgz", @@ -10077,6 +10094,21 @@ "dev": true, "license": "ISC" }, + "node_modules/zrender": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.1.0.tgz", + "integrity": "sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/zustand": { "version": "5.0.12", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz", diff --git a/package.json b/package.json index 856554a..6c70d58 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@xterm/xterm": "6.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "echarts": "^6.1.0", "i18next": "^26.0.8", "lucide-react": "^1.14.0", "mammoth": "^1.12.0", diff --git a/src-tauri/build.rs b/src-tauri/build.rs index e18f551..05804b6 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -110,6 +110,7 @@ const COMMANDS: &[&str] = &[ "artifact_delete_or_expire", "append_content_block", "get_message_blocks", + "chart_export_csv", ]; fn main() { diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index 99388fd..14e9210 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-append-content-block":{"identifier":"allow-append-content-block","description":"Enables the append_content_block command without any pre-configured scope.","commands":{"allow":["append_content_block"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-artifact-delete-or-expire":{"identifier":"allow-artifact-delete-or-expire","description":"Enables the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":["artifact_delete_or_expire"],"deny":[]}},"allow-artifact-export":{"identifier":"allow-artifact-export","description":"Enables the artifact_export command without any pre-configured scope.","commands":{"allow":["artifact_export"],"deny":[]}},"allow-artifact-get-metadata":{"identifier":"allow-artifact-get-metadata","description":"Enables the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":["artifact_get_metadata"],"deny":[]}},"allow-artifact-get-preview":{"identifier":"allow-artifact-get-preview","description":"Enables the artifact_get_preview command without any pre-configured scope.","commands":{"allow":["artifact_get_preview"],"deny":[]}},"allow-artifact-read-preview-base64":{"identifier":"allow-artifact-read-preview-base64","description":"Enables the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":["artifact_read_preview_base64"],"deny":[]}},"allow-artifact-register":{"identifier":"allow-artifact-register","description":"Enables the artifact_register command without any pre-configured scope.","commands":{"allow":["artifact_register"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-message-blocks":{"identifier":"allow-get-message-blocks","description":"Enables the get_message_blocks command without any pre-configured scope.","commands":{"allow":["get_message_blocks"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-append-content-block":{"identifier":"deny-append-content-block","description":"Denies the append_content_block command without any pre-configured scope.","commands":{"allow":[],"deny":["append_content_block"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-artifact-delete-or-expire":{"identifier":"deny-artifact-delete-or-expire","description":"Denies the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_delete_or_expire"]}},"deny-artifact-export":{"identifier":"deny-artifact-export","description":"Denies the artifact_export command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_export"]}},"deny-artifact-get-metadata":{"identifier":"deny-artifact-get-metadata","description":"Denies the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_metadata"]}},"deny-artifact-get-preview":{"identifier":"deny-artifact-get-preview","description":"Denies the artifact_get_preview command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_preview"]}},"deny-artifact-read-preview-base64":{"identifier":"deny-artifact-read-preview-base64","description":"Denies the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_read_preview_base64"]}},"deny-artifact-register":{"identifier":"deny-artifact-register","description":"Denies the artifact_register command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_register"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-message-blocks":{"identifier":"deny-get-message-blocks","description":"Denies the get_message_blocks command without any pre-configured scope.","commands":{"allow":[],"deny":["get_message_blocks"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall","artifact_register","artifact_get_metadata","artifact_get_preview","artifact_read_preview_base64","artifact_export","artifact_delete_or_expire","append_content_block","get_message_blocks"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-append-content-block":{"identifier":"allow-append-content-block","description":"Enables the append_content_block command without any pre-configured scope.","commands":{"allow":["append_content_block"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-artifact-delete-or-expire":{"identifier":"allow-artifact-delete-or-expire","description":"Enables the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":["artifact_delete_or_expire"],"deny":[]}},"allow-artifact-export":{"identifier":"allow-artifact-export","description":"Enables the artifact_export command without any pre-configured scope.","commands":{"allow":["artifact_export"],"deny":[]}},"allow-artifact-get-metadata":{"identifier":"allow-artifact-get-metadata","description":"Enables the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":["artifact_get_metadata"],"deny":[]}},"allow-artifact-get-preview":{"identifier":"allow-artifact-get-preview","description":"Enables the artifact_get_preview command without any pre-configured scope.","commands":{"allow":["artifact_get_preview"],"deny":[]}},"allow-artifact-read-preview-base64":{"identifier":"allow-artifact-read-preview-base64","description":"Enables the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":["artifact_read_preview_base64"],"deny":[]}},"allow-artifact-register":{"identifier":"allow-artifact-register","description":"Enables the artifact_register command without any pre-configured scope.","commands":{"allow":["artifact_register"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-chart-export-csv":{"identifier":"allow-chart-export-csv","description":"Enables the chart_export_csv command without any pre-configured scope.","commands":{"allow":["chart_export_csv"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-message-blocks":{"identifier":"allow-get-message-blocks","description":"Enables the get_message_blocks command without any pre-configured scope.","commands":{"allow":["get_message_blocks"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-append-content-block":{"identifier":"deny-append-content-block","description":"Denies the append_content_block command without any pre-configured scope.","commands":{"allow":[],"deny":["append_content_block"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-artifact-delete-or-expire":{"identifier":"deny-artifact-delete-or-expire","description":"Denies the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_delete_or_expire"]}},"deny-artifact-export":{"identifier":"deny-artifact-export","description":"Denies the artifact_export command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_export"]}},"deny-artifact-get-metadata":{"identifier":"deny-artifact-get-metadata","description":"Denies the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_metadata"]}},"deny-artifact-get-preview":{"identifier":"deny-artifact-get-preview","description":"Denies the artifact_get_preview command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_preview"]}},"deny-artifact-read-preview-base64":{"identifier":"deny-artifact-read-preview-base64","description":"Denies the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_read_preview_base64"]}},"deny-artifact-register":{"identifier":"deny-artifact-register","description":"Denies the artifact_register command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_register"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-chart-export-csv":{"identifier":"deny-chart-export-csv","description":"Denies the chart_export_csv command without any pre-configured scope.","commands":{"allow":[],"deny":["chart_export_csv"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-message-blocks":{"identifier":"deny-get-message-blocks","description":"Denies the get_message_blocks command without any pre-configured scope.","commands":{"allow":[],"deny":["get_message_blocks"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall","artifact_register","artifact_get_metadata","artifact_get_preview","artifact_read_preview_base64","artifact_export","artifact_delete_or_expire","append_content_block","get_message_blocks","chart_export_csv"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 6543194..0bce8f7 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -452,6 +452,12 @@ "const": "allow-browse-directory", "markdownDescription": "Enables the browse_directory command without any pre-configured scope." }, + { + "description": "Enables the chart_export_csv command without any pre-configured scope.", + "type": "string", + "const": "allow-chart-export-csv", + "markdownDescription": "Enables the chart_export_csv command without any pre-configured scope." + }, { "description": "Enables the create_router_config command without any pre-configured scope.", "type": "string", @@ -1118,6 +1124,12 @@ "const": "deny-browse-directory", "markdownDescription": "Denies the browse_directory command without any pre-configured scope." }, + { + "description": "Denies the chart_export_csv command without any pre-configured scope.", + "type": "string", + "const": "deny-chart-export-csv", + "markdownDescription": "Denies the chart_export_csv command without any pre-configured scope." + }, { "description": "Denies the create_router_config command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/windows-schema.json b/src-tauri/gen/schemas/windows-schema.json index 6543194..0bce8f7 100644 --- a/src-tauri/gen/schemas/windows-schema.json +++ b/src-tauri/gen/schemas/windows-schema.json @@ -452,6 +452,12 @@ "const": "allow-browse-directory", "markdownDescription": "Enables the browse_directory command without any pre-configured scope." }, + { + "description": "Enables the chart_export_csv command without any pre-configured scope.", + "type": "string", + "const": "allow-chart-export-csv", + "markdownDescription": "Enables the chart_export_csv command without any pre-configured scope." + }, { "description": "Enables the create_router_config command without any pre-configured scope.", "type": "string", @@ -1118,6 +1124,12 @@ "const": "deny-browse-directory", "markdownDescription": "Denies the browse_directory command without any pre-configured scope." }, + { + "description": "Denies the chart_export_csv command without any pre-configured scope.", + "type": "string", + "const": "deny-chart-export-csv", + "markdownDescription": "Denies the chart_export_csv command without any pre-configured scope." + }, { "description": "Denies the create_router_config command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/permissions/main.toml b/src-tauri/permissions/main.toml index 59f20f8..cb2204d 100644 --- a/src-tauri/permissions/main.toml +++ b/src-tauri/permissions/main.toml @@ -108,4 +108,5 @@ commands.allow = [ "artifact_delete_or_expire", "append_content_block", "get_message_blocks", + "chart_export_csv", ] diff --git a/src-tauri/src/commands/chart.rs b/src-tauri/src/commands/chart.rs new file mode 100644 index 0000000..a9cad9b --- /dev/null +++ b/src-tauri/src/commands/chart.rs @@ -0,0 +1,104 @@ +use rusqlite::params; +use tauri::State; + +use crate::config; +use crate::services::artifacts::{ + ArtifactMetadata, ArtifactOrigin, ArtifactService, ContentSafetyPolicy, +}; +use crate::services::content::ChartSpecV1; +use crate::AppState; + +fn service() -> Result { + ArtifactService::new( + config::artifacts_dir().map_err(|error| error.to_string())?, + ContentSafetyPolicy::default(), + ) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn chart_export_csv( + state: State<'_, AppState>, + session_id: String, + message_id: String, + spec: ChartSpecV1, +) -> Result { + if !state.feature_flags.rich_content_write { + return Err("CONTENT_BLOCK_UNSUPPORTED".to_string()); + } + + let service = service()?; + spec.validate(service.policy()) + .map_err(|error| error.to_string())?; + + let conn = state.db.lock().map_err(|error| error.to_string())?; + let message_belongs_to_session = conn + .query_row( + "SELECT EXISTS(SELECT 1 FROM messages WHERE id = ?1 AND session_id = ?2)", + params![message_id, session_id], + |row| row.get::<_, bool>(0), + ) + .map_err(|error| error.to_string())?; + if !message_belongs_to_session { + return Err("ARTIFACT_ACCESS_DENIED".to_string()); + } + + service + .register_bytes( + &conn, + session_id, + Some(message_id), + ArtifactOrigin::Agent, + "chart-data.csv".to_string(), + "text/csv".to_string(), + &chart_csv(&spec).into_bytes(), + ) + .map_err(|error| error.to_string()) +} + +fn chart_csv(spec: &ChartSpecV1) -> String { + let mut output = String::from("series,x,y\n"); + for series in &spec.series { + for datum in &series.values { + output.push_str(&csv_field(&series.name)); + output.push(','); + output.push_str(&csv_field(&datum.x)); + output.push(','); + output.push_str(&datum.y.to_string()); + output.push('\n'); + } + } + output +} + +fn csv_field(value: &str) -> String { + let value = if matches!(value.chars().next(), Some('=' | '+' | '-' | '@')) { + format!("'{value}") + } else { + value.to_owned() + }; + format!("\"{}\"", value.replace('"', "\"\"")) +} + +#[cfg(test)] +mod tests { + use super::{chart_csv, ChartSpecV1}; + + #[test] + fn csv_export_neutralizes_spreadsheet_formulas() { + let spec: ChartSpecV1 = serde_json::from_value(serde_json::json!({ + "chart_type": "line", + "title": "Sales", + "series": [{ + "name": "=danger", + "values": [{ "x": "+injection", "y": 12.0 }] + }] + })) + .unwrap(); + + assert_eq!( + chart_csv(&spec), + "series,x,y\n\"'=danger\",\"'+injection\",12\n" + ); + } +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index b05ee8d..e1f0918 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -1,4 +1,5 @@ pub mod artifacts; +pub mod chart; pub mod chat; pub mod fs_explorer; pub mod mcp; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index e193fd3..7069567 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -159,6 +159,7 @@ pub fn run() { commands::artifacts::artifact_delete_or_expire, commands::artifacts::append_content_block, commands::artifacts::get_message_blocks, + commands::chart::chart_export_csv, commands::fs_explorer::fs_list_dir, commands::fs_explorer::fs_read_text_file, commands::fs_explorer::fs_write_text_file, diff --git a/src/features/chat-content/renderers/ChartBlockRenderer.tsx b/src/features/chat-content/renderers/ChartBlockRenderer.tsx new file mode 100644 index 0000000..1f597ad --- /dev/null +++ b/src/features/chat-content/renderers/ChartBlockRenderer.tsx @@ -0,0 +1,184 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { BarChart3, Download, Table2 } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { Button } from "@/components/ui/button"; +import { artifactsIpc } from "@/lib/ipc"; +import type { BlockRendererProps } from "../renderer-registry"; +import { RichContentCard } from "../RichContentCard"; +import { readChartSpec, type ChartSpecV1 } from "./chart-types"; +import { NoticeBlockRenderer } from "./NoticeBlockRenderer"; + +export function ChartBlockRenderer({ block, sessionId }: BlockRendererProps) { + const { t } = useTranslation("chat"); + const spec = readChartSpec(block); + const [showTable, setShowTable] = useState(false); + const [exporting, setExporting] = useState(false); + const [error, setError] = useState(null); + + const exportCsv = useCallback(async () => { + if (!spec) return; + setExporting(true); + setError(null); + let artifactId: string | null = null; + try { + const metadata = await artifactsIpc.exportChartCsv(sessionId, block.message_id, spec); + artifactId = metadata.artifact_id; + await artifactsIpc.export(sessionId, metadata.artifact_id); + } catch { + setError(t("richContent.chart.exportFailed")); + } finally { + if (artifactId) void artifactsIpc.expire(sessionId, artifactId); + setExporting(false); + } + }, [block.message_id, sessionId, spec, t]); + + if (!spec) return ; + + return ( + } + status={block.status} + actions={ + <> + + + + } + footer={ + error ? {error} : spec.summary || t("richContent.chart.localOnly") + } + > + {spec.chart_type === "metric" ? : } + {showTable ? : null} + + ); +} + +function ChartCanvas({ spec }: { spec: ChartSpecV1 }) { + const { t } = useTranslation("chat"); + const elementRef = useRef(null); + const [error, setError] = useState(false); + const option = useMemo(() => compileChartOption(spec), [spec]); + + useEffect(() => { + const element = elementRef.current; + if (!element) return; + let disposed = false; + let instance: { resize: () => void; dispose: () => void } | null = null; + let resizeObserver: ResizeObserver | null = null; + + void import("echarts") + .then((echarts) => { + if (disposed) return; + const chart = echarts.init(element, undefined, { renderer: "canvas" }); + chart.setOption(option, { notMerge: true, lazyUpdate: true }); + instance = chart; + resizeObserver = new ResizeObserver(() => chart.resize()); + resizeObserver.observe(element); + }) + .catch(() => !disposed && setError(true)); + + return () => { + disposed = true; + resizeObserver?.disconnect(); + instance?.dispose(); + }; + }, [option]); + + if (error) { + return ; + } + return
; +} + +function MetricPreview({ spec }: { spec: ChartSpecV1 }) { + const { t } = useTranslation("chat"); + const values = spec.series[0]?.values ?? []; + const latest = values[values.length - 1]; + return ( +
+

{spec.series[0]?.name ?? t("richContent.chart.metric")}

+

{latest ? `${latest.y}${spec.unit ?? ""}` : "—"}

+ {latest?.x ?

{latest.x}

: null} +
+ ); +} + +function ChartDataTable({ spec, label }: { spec: ChartSpecV1; label?: string }) { + const { t } = useTranslation("chat"); + return ( +
+ {label ?

{label}

: null} + + + + + + + + + + {spec.series.flatMap((series) => series.values.map((datum, index) => ( + + + + + + )))} + +
{t("richContent.chart.series")}{spec.x_label ?? t("richContent.chart.x")}{spec.y_label ?? t("richContent.chart.y")}
{series.name}{datum.x}{datum.y}{spec.unit ?? ""}
+
+ ); +} + +function compileChartOption(spec: ChartSpecV1) { + const categories = [...new Set(spec.series.flatMap((series) => series.values.map((item) => item.x)))]; + const colors = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"]; + const unitSuffix = spec.unit ? ` ${spec.unit}` : ""; + const series = spec.series.map((item, index) => { + const values = item.values.map((datum) => ({ value: spec.chart_type === "scatter" ? [datum.x, datum.y] : datum.y, name: datum.label ?? datum.x })); + if (spec.chart_type === "pie") return { type: "pie", name: item.name, radius: ["35%", "66%"], data: values.map((value, valueIndex) => ({ value: item.values[valueIndex].y, name: value.name })) }; + return { + type: spec.chart_type === "area" ? "line" : spec.chart_type, + name: item.name, + data: values, + smooth: spec.chart_type === "line" || spec.chart_type === "area", + areaStyle: spec.chart_type === "area" ? { opacity: 0.16 } : undefined, + symbolSize: spec.chart_type === "scatter" ? 8 : undefined, + itemStyle: { color: colors[index % colors.length] }, + lineStyle: { color: colors[index % colors.length] }, + }; + }); + return { + animation: false, + aria: { enabled: true, decal: { show: true } }, + color: colors, + grid: spec.chart_type === "pie" ? undefined : { top: 32, right: 24, bottom: 36, left: 48, containLabel: true }, + tooltip: { + trigger: spec.chart_type === "pie" ? "item" : "axis", + renderMode: "richText", + valueFormatter: `{value}${unitSuffix}`, + }, + legend: { show: spec.series.length > 1, bottom: 0, type: "scroll" }, + xAxis: spec.chart_type === "pie" ? undefined : { type: "category", name: spec.x_label, data: categories, axisLabel: { hideOverlap: true } }, + yAxis: spec.chart_type === "pie" ? undefined : { type: "value", name: spec.y_label, axisLabel: { formatter: `{value}${unitSuffix}` } }, + series, + }; +} diff --git a/src/features/chat-content/renderers/chart-types.ts b/src/features/chat-content/renderers/chart-types.ts new file mode 100644 index 0000000..c736bcd --- /dev/null +++ b/src/features/chat-content/renderers/chart-types.ts @@ -0,0 +1,94 @@ +import type { ContentBlock } from "@/lib/ipc"; + +export type ChartType = "line" | "bar" | "area" | "scatter" | "pie" | "metric"; + +export interface ChartDatum { + x: string; + y: number; + label?: string; +} + +export interface ChartSeries { + name: string; + values: ChartDatum[]; +} + +export interface ChartSpecV1 { + chart_type: ChartType; + title: string; + summary?: string; + x_label?: string; + y_label?: string; + unit?: string; + series: ChartSeries[]; +} + +const MAX_SERIES = 24; +const MAX_POINTS = 5_000; +const MAX_LABEL_CHARS = 512; + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function isString(value: unknown): value is string { + return typeof value === "string"; +} + +export function readChartSpec(block: ContentBlock): ChartSpecV1 | null { + if (!isRecord(block.payload)) return null; + const candidate = isRecord(block.payload.spec) ? block.payload.spec : block.payload; + if (!isString(candidate.chart_type) || !isString(candidate.title) || !Array.isArray(candidate.series)) { + return null; + } + const chartTypes: ChartType[] = ["line", "bar", "area", "scatter", "pie", "metric"]; + if ( + !chartTypes.includes(candidate.chart_type as ChartType) + || candidate.title.trim().length === 0 + || candidate.title.length > MAX_LABEL_CHARS + || candidate.series.length === 0 + || candidate.series.length > MAX_SERIES + ) { + return null; + } + let points = 0; + const series = candidate.series.flatMap((rawSeries) => { + if ( + !isRecord(rawSeries) + || !isString(rawSeries.name) + || rawSeries.name.trim().length === 0 + || rawSeries.name.length > MAX_LABEL_CHARS + || !Array.isArray(rawSeries.values) + ) { + return []; + } + const values = rawSeries.values.flatMap((item) => { + if ( + !isRecord(item) + || !isString(item.x) + || item.x.length > MAX_LABEL_CHARS + || typeof item.y !== "number" + || !Number.isFinite(item.y) + || (item.label !== undefined && !isString(item.label)) + || (isString(item.label) && item.label.length > MAX_LABEL_CHARS) + ) { + return []; + } + points += 1; + if (points > MAX_POINTS) return []; + return [{ x: item.x, y: item.y, label: isString(item.label) ? item.label : undefined }]; + }); + if (values.length !== rawSeries.values.length) return []; + return [{ name: rawSeries.name, values }]; + }); + if (series.length !== candidate.series.length || points > MAX_POINTS) return null; + return { + chart_type: candidate.chart_type as ChartType, + title: candidate.title, + summary: isString(candidate.summary) ? candidate.summary : undefined, + x_label: isString(candidate.x_label) ? candidate.x_label : undefined, + y_label: isString(candidate.y_label) ? candidate.y_label : undefined, + unit: isString(candidate.unit) ? candidate.unit : undefined, + series, + }; +} diff --git a/src/lib/ipc/artifacts.ts b/src/lib/ipc/artifacts.ts index a5998f7..45e2e58 100644 --- a/src/lib/ipc/artifacts.ts +++ b/src/lib/ipc/artifacts.ts @@ -20,6 +20,8 @@ export const artifactsIpc = { invoke("artifact_export", { sessionId, artifactId }), expire: (sessionId: string, artifactId: string) => invoke("artifact_delete_or_expire", { sessionId, artifactId }), + exportChartCsv: (sessionId: string, messageId: string, spec: unknown) => + invoke("chart_export_csv", { sessionId, messageId, spec }), appendBlock: (block: ContentBlock) => invoke("append_content_block", { block }), getMessageBlocks: (messageId: string) => From 039f4c1ed592d34e316c0b8f81b75a00d022df38 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 08:43:52 +0800 Subject: [PATCH 13/16] fix(rich-content): stabilize r3 Windows CI --- .../06-implementation-log.md | 12 ++++++++++- src-tauri/tests/terminal_manager_tests.rs | 20 ++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index d1572a5..8c3105e 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -174,11 +174,21 @@ - **验证:** `cargo fmt --check` → pass;`cargo clippy --all-targets --all-features -- -D warnings` → pass;`cargo test --all-features --lib chart` → 2 passed / 0 failed;`cargo test --all-features --test security_config_baseline_tests` → 5 passed / 0 failed;`npm run build` → pass(动态 chunk 大小 warning);`npm test -- --run` → 38 files / 271 passed(JSDOM canvas diagnostic,exit 0)。 - **未验证:** 未进行真实屏幕阅读器、手工深浅主题/窗口缩放或大量 series 的交互回归;R4 地图代码、MapLibre 依赖和 GeoJSON 导出未纳入暂存。 - **Git:** 待提交;暂存范围为 R3 图表、CSV 导出、受控命令权限、ECharts 依赖与本记录。 -- **远程 CI:** 待 R3 commit 推送后运行。 +- **远程 CI:** 初始 [CI #31286615412](https://github.com/knqiufan/MisakaX/actions/runs/31286615412) 的 Rust、Frontend 与 Linux/macOS Terminal Runtime 成功;Windows Terminal Runtime 在 `shutdown_reaps_shell_and_grandchild_process_tree` 读到刚创建但尚为空的 PID 文件后失败,Tauri Build 因依赖失败被跳过。已完成当前阶段的测试竞态修复,等待新的完整运行。 - **风险/回滚:** 回滚本阶段可恢复 chart→notice fallback;CSV 导出临时 artifact 会在客户端导出流程完成后 expire,不产生通用文件写入权限。 - **文档同步:** R2 已同步的 `frontend-ui-guidelines.md` §4.6.x.1 对图表的通用规范继续适用;本实施记录补充实现证据。 - **下一步:** 审查 R3 暂存差异、提交并等待 remote CI 全绿;之后才开始 R4。 +### 2026-08-09 — R3:Windows Terminal Runtime PID 文件竞态修复 + +- **范围:** 修复 [CI #31286615412](https://github.com/knqiufan/MisakaX/actions/runs/31286615412) 暴露的既有 Windows 终端集成测试竞态;未改变图表、Tauri command、artifact 或运行时终端服务。 +- **代码审查:** 测试此前仅等待 PID 文件存在,但 PowerShell `Set-Content` 会先创建文件、后写入 PID。改为在 8 秒既有启动期限内等待可解析的数值 PID;子进程存在性、`manager.shutdown()`、进程回收及活跃数量断言保持不变,未放宽行为性验收。 +- **验证:** `cargo fmt --check` → pass;`cargo test --all-features --test terminal_manager_tests -- --nocapture` → 10 passed / 0 failed;`cargo clippy --all-targets --all-features -- -D warnings` → pass。 +- **Git:** 待提交为 R3 CI 修复。 +- **远程 CI:** 待推送后重新运行;R3 保持未完成。 +- **风险/回滚:** 仅测试同步调整;若需回退则恢复原有文件存在检查,但 Windows CI 可能复现空文件竞态。 +- **下一步:** 推送修复并等待 R3 全部远程 required checks 成功。 + ## 后续记录模板 ```markdown diff --git a/src-tauri/tests/terminal_manager_tests.rs b/src-tauri/tests/terminal_manager_tests.rs index 7a3122d..365f4ca 100644 --- a/src-tauri/tests/terminal_manager_tests.rs +++ b/src-tauri/tests/terminal_manager_tests.rs @@ -642,15 +642,21 @@ fn shutdown_reaps_shell_and_grandchild_process_tree() { ) .unwrap(); + // Set-Content creates the file before the PID bytes are visible. On cold + // Windows CI workers, observing that short intermediate state is normal. let deadline = Instant::now() + Duration::from_secs(8); - while !pid_file.exists() && Instant::now() < deadline { + let pid = loop { + if let Ok(value) = std::fs::read_to_string(&pid_file) { + if let Ok(pid) = value.trim().parse::() { + break pid; + } + } + assert!( + Instant::now() < deadline, + "numeric grandchild pid was not written before the deadline" + ); std::thread::sleep(Duration::from_millis(50)); - } - let pid = std::fs::read_to_string(&pid_file) - .expect("grandchild pid file") - .trim() - .parse::() - .expect("numeric grandchild pid"); + }; assert!(process_exists(pid)); manager.shutdown(); From ee6eea714682368b3a62105f3c8028296717bc40 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 08:57:42 +0800 Subject: [PATCH 14/16] fix(rich-content): register r3 chart renderer --- .../rich-content-delivery/06-implementation-log.md | 10 ++++++++++ src/features/chat-content/renderer-registry.tsx | 5 ++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index 8c3105e..c6166cf 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -189,6 +189,16 @@ - **风险/回滚:** 仅测试同步调整;若需回退则恢复原有文件存在检查,但 Windows CI 可能复现空文件竞态。 - **下一步:** 推送修复并等待 R3 全部远程 required checks 成功。 +### 2026-08-09 — R3:图表渲染器注册收口 + +- **范围:** 仅修复 R3 的前端接线:将 `chart` 块从安全的 `NoticeBlockRenderer` fallback 映射至已审查的 `ChartBlockRenderer`;`map` 继续保留 fallback,未提前纳入 R4。 +- **代码审查:** 在阶段复核时发现先前的图表 renderer、受限 ChartSpec parser 与 CSV 导出均已落地,但 renderer registry 漏掉了 `ChartBlockRenderer` 导入和注册,导致图表在 UI 中不可达。本修复不新增 payload 能力、依赖、CSP 或 Tauri capability;R2 的未知/地图非执行 fallback 仍然生效。 +- **验证:** `npm run build` ⇒ pass(仅保留既有大动态 chunk 警告);`npm test -- --run` ⇒ 38 files / 271 passed(JSDOM canvas diagnostic,exit 0)。 +- **Git:** 待以独立 R3 收口 commit 推送至 `codex/rich-content-r0-r4`。 +- **远程 CI:** 前序 R3 运行 [CI #31286802359](https://github.com/knqiufan/MisakaX/actions/runs/31286802359) 已 8/8 成功;本接线修复仍须重新完成完整远程 CI,故 R3 暂不标记为完成。 +- **风险/回滚:** 回退本 commit 即恢复 `chart` 的不可执行 notice fallback;不会影响 R0–R2 或 R4 候选改动。 +- **下一步:** 审查该独立切片、非强制推送并等待全部远程检查成功后再继续 R4。 + ## 后续记录模板 ```markdown diff --git a/src/features/chat-content/renderer-registry.tsx b/src/features/chat-content/renderer-registry.tsx index 6e40193..6e3e065 100644 --- a/src/features/chat-content/renderer-registry.tsx +++ b/src/features/chat-content/renderer-registry.tsx @@ -2,6 +2,7 @@ import type { ComponentType } from "react"; import type { ContentBlock } from "@/lib/ipc"; import { ArtifactBlockRenderer } from "./renderers/ArtifactBlockRenderer"; +import { ChartBlockRenderer } from "./renderers/ChartBlockRenderer"; import { ImageBlockRenderer } from "./renderers/ImageBlockRenderer"; import { MarkdownBlockRenderer } from "./renderers/MarkdownBlockRenderer"; import { NoticeBlockRenderer } from "./renderers/NoticeBlockRenderer"; @@ -14,9 +15,7 @@ export interface BlockRendererProps { const REGISTRY: Record> = { markdown: MarkdownBlockRenderer, - // Chart and map blocks are deliberately non-executing until their own - // renderer phases complete; their persisted fallback remains readable. - chart: NoticeBlockRenderer, + chart: ChartBlockRenderer, map: NoticeBlockRenderer, artifact: ArtifactBlockRenderer, image: ImageBlockRenderer, From 0a641237c9f8cfe582d1809fdcb7424f495394ab Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 09:18:33 +0800 Subject: [PATCH 15/16] feat(rich-content): complete r4 local GeoJSON maps --- docs/design/frontend-ui-guidelines.md | 3 +- .../06-implementation-log.md | 20 +- package-lock.json | 203 ++++++++++++++++++ package.json | 1 + src-tauri/build.rs | 1 + src-tauri/gen/schemas/acl-manifests.json | 2 +- src-tauri/gen/schemas/desktop-schema.json | 12 ++ src-tauri/gen/schemas/windows-schema.json | 12 ++ src-tauri/permissions/main.toml | 1 + src-tauri/src/commands/map.rs | 91 ++++++++ src-tauri/src/commands/mod.rs | 1 + src-tauri/src/lib.rs | 1 + src-tauri/src/services/artifacts/service.rs | 18 +- src/__tests__/rich-content-map.test.ts | 57 +++++ src/features/chat-content/RichContentCard.tsx | 3 + .../chat-content/renderer-registry.tsx | 3 +- .../renderers/MapBlockRenderer.tsx | 184 ++++++++++++++++ .../chat-content/renderers/map-types.ts | 164 ++++++++++++++ src/lib/ipc/artifacts.ts | 2 + src/locales/en/chat.json | 4 +- src/locales/zh-CN/chat.json | 4 +- 21 files changed, 778 insertions(+), 9 deletions(-) create mode 100644 src-tauri/src/commands/map.rs create mode 100644 src/__tests__/rich-content-map.test.ts create mode 100644 src/features/chat-content/renderers/MapBlockRenderer.tsx create mode 100644 src/features/chat-content/renderers/map-types.ts diff --git a/docs/design/frontend-ui-guidelines.md b/docs/design/frontend-ui-guidelines.md index de264b8..4a17683 100644 --- a/docs/design/frontend-ui-guidelines.md +++ b/docs/design/frontend-ui-guidelines.md @@ -8,7 +8,7 @@ - **按钮、下拉菜单、Popover、Select、Dialog、Tooltip 等控件的细节与变体**:编写或调整时须同时对照 [button-menu-design-spec.md](./button-menu-design-spec.md)。 - **可复刻参考(CodePilot)**:[`docs/ui/02-chat.md`](../ui/02-chat.md)、[`docs/ui/03-workspace.md`](../ui/03-workspace.md)、[`docs/ui/04-settings.md`](../ui/04-settings.md)、[`docs/ui/06-markdown-message-tools.md`](../ui/06-markdown-message-tools.md)(视觉与能力对齐;IA 以 shell 规范本期边界为准)。 -**最后审阅 / Last reviewed:** 2026-08-09(v33) +**最后审阅 / Last reviewed:** 2026-08-09(v34) ## 1. 设计理念 (Design Philosophy) @@ -214,6 +214,7 @@ MisakaX 的目标是打造一个**现代化、专业、克制的桌面端 Agent - 图表、地图、文件预览必须惰性加载,并提供受控的文本/数据/下载降级路径;块级失败只能显示局部 notice,不能中断相邻 Markdown、工具调用或消息 footer。 - 文件预览使用共享 `Dialog`,始终标明“只读”;二进制资源仅经窄 IPC 获取,禁止在 JSX 注入 HTML、任意 URL、`file:` 路径或未验证 SVG。所有可见标签、状态、`aria-label` 和错误文案必须走 `chat.richContent.*` i18n key。 - 图表和地图的辅助操作(数据表、要素列表、复制、导出)必须键盘可达;颜色不是唯一信息来源,库加载/WebGL 失败时显示等价文本数据。 +- R4a 地图只渲染经校验的本地 GeoJSON:不得接收 tile URL、外部样式或其他远程资源;地图区域保持中性底色、固定可读高度和加载态,渲染失败时回退为要素列表。长要素列表默认最多显示 200 项,并明确告知截断。 ### 4.6.y 工具调用状态行(ToolActionsGroup) diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index c6166cf..0efe517 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0、R1、R2 已通过远程全量 CI。R3 图表已完成本地验证,待阶段提交、推送与远程 CI;R4 尚未开始阶段提交。 +> **状态:** R0–R3 已通过远程全量 CI。R4 地图已完成本地验证,待阶段提交、推送与远程 CI。 --- @@ -23,8 +23,8 @@ | R0 契约/安全基线 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `b1ed884`;[CI #31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 的 8 项检查全绿 | | R1 ArtifactService/图片/下载 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `53a079d`;[CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 8 项检查全绿 | | R2 文件预览 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `2e979e1`;[CI #31285793427](https://github.com/knqiufan/MisakaX/actions/runs/31285793427) 的 8 项检查全绿 | -| R3 图表 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限 ChartSpec、ECharts richText、可访问数据表和 ArtifactService CSV 导出;待 commit/push/CI | -| R4 地图 | 未开始阶段门禁 | 待分配 | — | — | 候选工作区改动未提交、未验证、未推送;R4b 不在范围内 | +| R3 图表 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `ee6eea7`;[CI #31287278455](https://github.com/knqiufan/MisakaX/actions/runs/31287278455) 的 8 项检查全绿 | +| R4 地图 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限本地 GeoJSON、MapLibre fallback 与 ArtifactService 导出;待 commit/push/CI,R4b 不在范围内 | | R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | | R6 加固/发布 | 未开始 | 待分配 | — | — | 三平台/沙箱 gate;通过阶段门禁后完成 | @@ -199,6 +199,20 @@ - **风险/回滚:** 回退本 commit 即恢复 `chart` 的不可执行 notice fallback;不会影响 R0–R2 或 R4 候选改动。 - **下一步:** 审查该独立切片、非强制推送并等待全部远程检查成功后再继续 R4。 +### 2026-08-09 — R4a:受限本地 GeoJSON 地图与导出 + +- **范围:** 启用 `map` 块的 MapLibre renderer、要素列表/复制/GeoJSON 导出和局部降级;只使用内嵌的空数据源 style 及已持久化的 GeoJSON。R4b 的远程瓦片、provider registry、网络代理、隐私提示和 CSP 扩展均不在范围内。 +- **修改:** 新增防御性 MapSpec parser(10,000 要素/marker、24 properties、512 字符标签、有限且有界坐标);地图加载失败时展示要素列表,最多渲染 200 条列表项;增加 `map_export_geojson` Rust command、受管 artifact 导出、窄 IPC、AppManifest/权限/schema 同步、MapLibre 依赖、双语文案及 parser 回归测试。 +- **安全影响:** parser 与 Rust `MapSpecV1` 同时拒绝 `tile_source_id`;没有 tile URL、外部 style、HTML、`file:` 路径或任意网络输入。导出只序列化 `feature_collection`,先验证 feature flag、MapSpec 和消息的 session 归属,再通过 ArtifactService 写入 `application/geo+json`;未添加 FS/HTTP/Shell capability 或 CSP 放宽。 +- **代码审查:** 核对 renderer registry 已指向 `MapBlockRenderer`,动态加载只发生在块渲染时;数据来源/attribution 位于卡片 header,视图可复位;WebGL/MapLibre 错误不会影响相邻块;Clipboard 使用 Tauri 插件;导出临时 artifact 在保存流程结束后 expire。命令已同时出现在 `invoke_handler`、AppManifest 和最小权限白名单,权限基线测试覆盖该集合。 +- **验证:** `cargo fmt --check` ⇒ pass;`cargo test --all-features --lib map` ⇒ 3 passed;`cargo test --all-features --lib artifact` ⇒ 8 passed;`cargo test --all-features --test security_config_baseline_tests` ⇒ 5 passed;`cargo clippy --all-targets --all-features -- -D warnings` ⇒ pass;`npm test -- --run` ⇒ 39 files / 273 passed;`npm run build` ⇒ pass(既有大动态 chunk warning)。 +- **未验证:** 未在三平台真实 GPU/WebGL、屏幕阅读器、窗口缩放或实际保存对话框中手工回归;JSDOM 的 canvas diagnostic 不影响测试 exit 0。远程 CI 尚未执行。 +- **Git:** 待以独立 R4a commit 推送至 `codex/rich-content-r0-r4`。 +- **远程 CI:** 待非强制 push 后触发并完成 8 项 required checks;在全绿前 R4 不标记完成。 +- **风险/回滚:** 回退 R4a commit 即恢复 `map` 的不可执行 notice fallback;不会放宽 CSP 或现有通用文件/网络能力。MapLibre bundle 增量仅在地图 renderer 动态加载时下载。 +- **文档同步:** `docs/design/frontend-ui-guidelines.md` §4.6.x.1;本实施记录。 +- **下一步:** 审查 R4a 暂存差异、提交、非强制推送并等待远程 CI 全绿;随后更新阶段看板与 R0–R4 交接文档。 + ## 后续记录模板 ```markdown diff --git a/package-lock.json b/package-lock.json index d2c7c9b..fc40f37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "i18next": "^26.0.8", "lucide-react": "^1.14.0", "mammoth": "^1.12.0", + "maplibre-gl": "^6.2.0", "monaco-editor": "^0.55.1", "next-themes": "^0.4.6", "pdfjs-dist": "^6.2.108", @@ -1134,6 +1135,92 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.3.tgz", + "integrity": "sha512-0SElaV0uMxEnxzBhhX9WTuPyUeMsAN/SS0i16tjuba4/mio63MG9khjC1a0JAiPGXAwvwm4UfHJURCN7nyudQg==", + "license": "MIT", + "engines": { + "node": ">= 22" + } + }, + "node_modules/@mapbox/point-geometry": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", + "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==", + "license": "ISC" + }, + "node_modules/@mapbox/tiny-sdf": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz", + "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==", + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/unitbezier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-1.0.0.tgz", + "integrity": "sha512-fqd515fjBmANKGGsQ286E2Wvj/XvDFpGzwJxq4CI6jMQue6Oy04uCKp+JWKF00xRTmk6cEu1jPJ9p3xqH8YWqQ==", + "license": "BSD-2-Clause" + }, + "node_modules/@mapbox/vector-tile": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-3.0.0.tgz", + "integrity": "sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@mapbox/point-geometry": "~1.1.0", + "@types/geojson": "^7946.0.16", + "pbf": "^5.0.0" + } + }, + "node_modules/@maplibre/geojson-vt": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@maplibre/geojson-vt/-/geojson-vt-6.1.1.tgz", + "integrity": "sha512-FVMOcmSP/yqol45t7StApEyTL5/vmqBCuFhH9n+fFuINenhaX+YgHHIt1yJ86S8kln3uJLcMvmEU2cfn6E2eCQ==", + "license": "ISC", + "dependencies": { + "kdbush": "^4.1.0" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "26.2.1", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-26.2.1.tgz", + "integrity": "sha512-QFKCXkOeSzOr8jF75jm6kySOg+dUvOehPhRi68gcOYPHb7U5JloUq0dJW0Y5/fZV8ygfT0Vp2RWodvq+fyxFWA==", + "license": "ISC", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "^2.0.3", + "@mapbox/unitbezier": "^1.0.0", + "json-stringify-pretty-compact": "^4.0.0", + "minimist": "^1.2.8", + "quickselect": "^3.0.0", + "tinyqueue": "^3.0.0" + }, + "bin": { + "gl-style-format": "dist/gl-style-format.mjs", + "gl-style-migrate": "dist/gl-style-migrate.mjs", + "gl-style-validate": "dist/gl-style-validate.mjs" + } + }, + "node_modules/@maplibre/mlt": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@maplibre/mlt/-/mlt-1.1.12.tgz", + "integrity": "sha512-ZeK5w2TTeHOajcLaEQs1KZXw2V9wIKo1PmThlxlsHoXsQsYlBqLJzPOd6tJHRtGTChUY3DPPmjXRArYVvAbmZw==", + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "@mapbox/point-geometry": "^1.1.0" + } + }, + "node_modules/@maplibre/vt-pbf": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@maplibre/vt-pbf/-/vt-pbf-4.3.2.tgz", + "integrity": "sha512-j6p0AdjvAR19Z3XaCysle7A4ZSo08tYOzxD0Y9NQylwPAkwJJeYub5b2eVucdeDh7erhv69DahoLOevDRERRUw==", + "license": "MIT", + "dependencies": { + "@mapbox/point-geometry": "^1.1.0", + "@types/geojson": "^7946.0.16", + "pbf": "^5.1.0" + } + }, "node_modules/@mermaid-js/parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.2.0.tgz", @@ -5951,6 +6038,12 @@ "underscore": "^1.13.1" } }, + "node_modules/earcut": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.2.3.tgz", + "integrity": "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==", + "license": "ISC" + }, "node_modules/echarts": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.1.0.tgz", @@ -6187,6 +6280,12 @@ "node": ">=6" } }, + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "license": "MIT" + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -6765,6 +6864,12 @@ "node": ">=6" } }, + "node_modules/json-stringify-pretty-compact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz", + "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==", + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -6806,6 +6911,12 @@ "katex": "cli.js" } }, + "node_modules/kdbush": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.1.0.tgz", + "integrity": "sha512-e9vurzrXJQrFX6ckpHP3bvj5l+9CnYzkxDNnNQ1h2QTqdWsUAJgXiKdGNcOa1EY85dU8KbQ+z/FdQdB7P+9yfQ==", + "license": "ISC" + }, "node_modules/khroma": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", @@ -7177,6 +7288,38 @@ "node": ">=12.0.0" } }, + "node_modules/maplibre-gl": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-6.2.0.tgz", + "integrity": "sha512-PaNYtxWmYgIdDHshXsnU3Pho+H9IPme9H6dTjZbFWNazi+Q5QgKgIlu2GiSGVtOZ77/Fz3n5/1/kGM6ETzu0Lg==", + "license": "BSD-3-Clause", + "dependencies": { + "@mapbox/point-geometry": "^1.1.0", + "@mapbox/tiny-sdf": "^2.2.0", + "@mapbox/unitbezier": "^1.0.0", + "@mapbox/vector-tile": "^3.0.0", + "@maplibre/geojson-vt": "^6.1.1", + "@maplibre/maplibre-gl-style-spec": "^26.2.1", + "@maplibre/mlt": "^1.1.12", + "@maplibre/vt-pbf": "^4.3.2", + "@types/geojson": "^7946.0.16", + "earcut": "^3.2.3", + "gl-matrix": "^3.4.4", + "kdbush": "^4.1.0", + "murmurhash-js": "^1.0.0", + "pbf": "^5.1.2", + "potpack": "^2.1.0", + "quickselect": "^3.0.0", + "tinyqueue": "^3.0.0" + }, + "engines": { + "node": ">=16.14.0", + "npm": ">=8.1.0" + }, + "funding": { + "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -8243,6 +8386,15 @@ ], "license": "MIT" }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/monaco-editor": { "version": "0.55.1", "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", @@ -8259,6 +8411,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", @@ -8400,6 +8558,18 @@ "dev": true, "license": "MIT" }, + "node_modules/pbf": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-5.1.2.tgz", + "integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, "node_modules/pdfjs-dist": { "version": "6.2.108", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-6.2.108.tgz", @@ -8474,6 +8644,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/potpack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz", + "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==", + "license": "ISC" + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -8506,6 +8682,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", + "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8516,6 +8698,12 @@ "node": ">=6" } }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, "node_modules/radix-ui": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz", @@ -9021,6 +9209,15 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, "node_modules/robust-predicates": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", @@ -9384,6 +9581,12 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", + "license": "ISC" + }, "node_modules/tinyrainbow": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", diff --git a/package.json b/package.json index 6c70d58..81cdbaa 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "i18next": "^26.0.8", "lucide-react": "^1.14.0", "mammoth": "^1.12.0", + "maplibre-gl": "^6.2.0", "monaco-editor": "^0.55.1", "next-themes": "^0.4.6", "pdfjs-dist": "^6.2.108", diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 05804b6..41dceac 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -111,6 +111,7 @@ const COMMANDS: &[&str] = &[ "append_content_block", "get_message_blocks", "chart_export_csv", + "map_export_geojson", ]; fn main() { diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index 14e9210..18568d8 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-append-content-block":{"identifier":"allow-append-content-block","description":"Enables the append_content_block command without any pre-configured scope.","commands":{"allow":["append_content_block"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-artifact-delete-or-expire":{"identifier":"allow-artifact-delete-or-expire","description":"Enables the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":["artifact_delete_or_expire"],"deny":[]}},"allow-artifact-export":{"identifier":"allow-artifact-export","description":"Enables the artifact_export command without any pre-configured scope.","commands":{"allow":["artifact_export"],"deny":[]}},"allow-artifact-get-metadata":{"identifier":"allow-artifact-get-metadata","description":"Enables the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":["artifact_get_metadata"],"deny":[]}},"allow-artifact-get-preview":{"identifier":"allow-artifact-get-preview","description":"Enables the artifact_get_preview command without any pre-configured scope.","commands":{"allow":["artifact_get_preview"],"deny":[]}},"allow-artifact-read-preview-base64":{"identifier":"allow-artifact-read-preview-base64","description":"Enables the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":["artifact_read_preview_base64"],"deny":[]}},"allow-artifact-register":{"identifier":"allow-artifact-register","description":"Enables the artifact_register command without any pre-configured scope.","commands":{"allow":["artifact_register"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-chart-export-csv":{"identifier":"allow-chart-export-csv","description":"Enables the chart_export_csv command without any pre-configured scope.","commands":{"allow":["chart_export_csv"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-message-blocks":{"identifier":"allow-get-message-blocks","description":"Enables the get_message_blocks command without any pre-configured scope.","commands":{"allow":["get_message_blocks"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-append-content-block":{"identifier":"deny-append-content-block","description":"Denies the append_content_block command without any pre-configured scope.","commands":{"allow":[],"deny":["append_content_block"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-artifact-delete-or-expire":{"identifier":"deny-artifact-delete-or-expire","description":"Denies the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_delete_or_expire"]}},"deny-artifact-export":{"identifier":"deny-artifact-export","description":"Denies the artifact_export command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_export"]}},"deny-artifact-get-metadata":{"identifier":"deny-artifact-get-metadata","description":"Denies the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_metadata"]}},"deny-artifact-get-preview":{"identifier":"deny-artifact-get-preview","description":"Denies the artifact_get_preview command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_preview"]}},"deny-artifact-read-preview-base64":{"identifier":"deny-artifact-read-preview-base64","description":"Denies the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_read_preview_base64"]}},"deny-artifact-register":{"identifier":"deny-artifact-register","description":"Denies the artifact_register command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_register"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-chart-export-csv":{"identifier":"deny-chart-export-csv","description":"Denies the chart_export_csv command without any pre-configured scope.","commands":{"allow":[],"deny":["chart_export_csv"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-message-blocks":{"identifier":"deny-get-message-blocks","description":"Denies the get_message_blocks command without any pre-configured scope.","commands":{"allow":[],"deny":["get_message_blocks"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall","artifact_register","artifact_get_metadata","artifact_get_preview","artifact_read_preview_base64","artifact_export","artifact_delete_or_expire","append_content_block","get_message_blocks","chart_export_csv"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"__app-acl__":{"default_permission":null,"permissions":{"allow-add-custom-model":{"identifier":"allow-add-custom-model","description":"Enables the add_custom_model command without any pre-configured scope.","commands":{"allow":["add_custom_model"],"deny":[]}},"allow-append-content-block":{"identifier":"allow-append-content-block","description":"Enables the append_content_block command without any pre-configured scope.","commands":{"allow":["append_content_block"],"deny":[]}},"allow-archive-session":{"identifier":"allow-archive-session","description":"Enables the archive_session command without any pre-configured scope.","commands":{"allow":["archive_session"],"deny":[]}},"allow-artifact-delete-or-expire":{"identifier":"allow-artifact-delete-or-expire","description":"Enables the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":["artifact_delete_or_expire"],"deny":[]}},"allow-artifact-export":{"identifier":"allow-artifact-export","description":"Enables the artifact_export command without any pre-configured scope.","commands":{"allow":["artifact_export"],"deny":[]}},"allow-artifact-get-metadata":{"identifier":"allow-artifact-get-metadata","description":"Enables the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":["artifact_get_metadata"],"deny":[]}},"allow-artifact-get-preview":{"identifier":"allow-artifact-get-preview","description":"Enables the artifact_get_preview command without any pre-configured scope.","commands":{"allow":["artifact_get_preview"],"deny":[]}},"allow-artifact-read-preview-base64":{"identifier":"allow-artifact-read-preview-base64","description":"Enables the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":["artifact_read_preview_base64"],"deny":[]}},"allow-artifact-register":{"identifier":"allow-artifact-register","description":"Enables the artifact_register command without any pre-configured scope.","commands":{"allow":["artifact_register"],"deny":[]}},"allow-backfill-session-workspaces":{"identifier":"allow-backfill-session-workspaces","description":"Enables the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":["backfill_session_workspaces"],"deny":[]}},"allow-browse-directory":{"identifier":"allow-browse-directory","description":"Enables the browse_directory command without any pre-configured scope.","commands":{"allow":["browse_directory"],"deny":[]}},"allow-chart-export-csv":{"identifier":"allow-chart-export-csv","description":"Enables the chart_export_csv command without any pre-configured scope.","commands":{"allow":["chart_export_csv"],"deny":[]}},"allow-create-router-config":{"identifier":"allow-create-router-config","description":"Enables the create_router_config command without any pre-configured scope.","commands":{"allow":["create_router_config"],"deny":[]}},"allow-create-router-config-with-models":{"identifier":"allow-create-router-config-with-models","description":"Enables the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":["create_router_config_with_models"],"deny":[]}},"allow-create-session":{"identifier":"allow-create-session","description":"Enables the create_session command without any pre-configured scope.","commands":{"allow":["create_session"],"deny":[]}},"allow-delete-custom-model":{"identifier":"allow-delete-custom-model","description":"Enables the delete_custom_model command without any pre-configured scope.","commands":{"allow":["delete_custom_model"],"deny":[]}},"allow-delete-router-config":{"identifier":"allow-delete-router-config","description":"Enables the delete_router_config command without any pre-configured scope.","commands":{"allow":["delete_router_config"],"deny":[]}},"allow-delete-session":{"identifier":"allow-delete-session","description":"Enables the delete_session command without any pre-configured scope.","commands":{"allow":["delete_session"],"deny":[]}},"allow-export-sessions":{"identifier":"allow-export-sessions","description":"Enables the export_sessions command without any pre-configured scope.","commands":{"allow":["export_sessions"],"deny":[]}},"allow-fetch-provider-models":{"identifier":"allow-fetch-provider-models","description":"Enables the fetch_provider_models command without any pre-configured scope.","commands":{"allow":["fetch_provider_models"],"deny":[]}},"allow-fs-list-dir":{"identifier":"allow-fs-list-dir","description":"Enables the fs_list_dir command without any pre-configured scope.","commands":{"allow":["fs_list_dir"],"deny":[]}},"allow-fs-read-text-file":{"identifier":"allow-fs-read-text-file","description":"Enables the fs_read_text_file command without any pre-configured scope.","commands":{"allow":["fs_read_text_file"],"deny":[]}},"allow-fs-reveal-in-explorer":{"identifier":"allow-fs-reveal-in-explorer","description":"Enables the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":["fs_reveal_in_explorer"],"deny":[]}},"allow-fs-write-text-file":{"identifier":"allow-fs-write-text-file","description":"Enables the fs_write_text_file command without any pre-configured scope.","commands":{"allow":["fs_write_text_file"],"deny":[]}},"allow-generate-session-title":{"identifier":"allow-generate-session-title","description":"Enables the generate_session_title command without any pre-configured scope.","commands":{"allow":["generate_session_title"],"deny":[]}},"allow-get-all-settings":{"identifier":"allow-get-all-settings","description":"Enables the get_all_settings command without any pre-configured scope.","commands":{"allow":["get_all_settings"],"deny":[]}},"allow-get-app-config":{"identifier":"allow-get-app-config","description":"Enables the get_app_config command without any pre-configured scope.","commands":{"allow":["get_app_config"],"deny":[]}},"allow-get-message-blocks":{"identifier":"allow-get-message-blocks","description":"Enables the get_message_blocks command without any pre-configured scope.","commands":{"allow":["get_message_blocks"],"deny":[]}},"allow-get-messages":{"identifier":"allow-get-messages","description":"Enables the get_messages command without any pre-configured scope.","commands":{"allow":["get_messages"],"deny":[]}},"allow-get-recent-directories":{"identifier":"allow-get-recent-directories","description":"Enables the get_recent_directories command without any pre-configured scope.","commands":{"allow":["get_recent_directories"],"deny":[]}},"allow-get-session":{"identifier":"allow-get-session","description":"Enables the get_session command without any pre-configured scope.","commands":{"allow":["get_session"],"deny":[]}},"allow-get-setting":{"identifier":"allow-get-setting","description":"Enables the get_setting command without any pre-configured scope.","commands":{"allow":["get_setting"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-get-sidecar-status":{"identifier":"allow-get-sidecar-status","description":"Enables the get_sidecar_status command without any pre-configured scope.","commands":{"allow":["get_sidecar_status"],"deny":[]}},"allow-get-system-info":{"identifier":"allow-get-system-info","description":"Enables the get_system_info command without any pre-configured scope.","commands":{"allow":["get_system_info"],"deny":[]}},"allow-import-sessions":{"identifier":"allow-import-sessions","description":"Enables the import_sessions command without any pre-configured scope.","commands":{"allow":["import_sessions"],"deny":[]}},"allow-list-available-models":{"identifier":"allow-list-available-models","description":"Enables the list_available_models command without any pre-configured scope.","commands":{"allow":["list_available_models"],"deny":[]}},"allow-list-custom-models":{"identifier":"allow-list-custom-models","description":"Enables the list_custom_models command without any pre-configured scope.","commands":{"allow":["list_custom_models"],"deny":[]}},"allow-list-router-configs":{"identifier":"allow-list-router-configs","description":"Enables the list_router_configs command without any pre-configured scope.","commands":{"allow":["list_router_configs"],"deny":[]}},"allow-list-session-groups":{"identifier":"allow-list-session-groups","description":"Enables the list_session_groups command without any pre-configured scope.","commands":{"allow":["list_session_groups"],"deny":[]}},"allow-list-sessions":{"identifier":"allow-list-sessions","description":"Enables the list_sessions command without any pre-configured scope.","commands":{"allow":["list_sessions"],"deny":[]}},"allow-list-workspace-preferences":{"identifier":"allow-list-workspace-preferences","description":"Enables the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":["list_workspace_preferences"],"deny":[]}},"allow-map-export-geojson":{"identifier":"allow-map-export-geojson","description":"Enables the map_export_geojson command without any pre-configured scope.","commands":{"allow":["map_export_geojson"],"deny":[]}},"allow-mcp-add-server-config":{"identifier":"allow-mcp-add-server-config","description":"Enables the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":["mcp_add_server_config"],"deny":[]}},"allow-mcp-approve-tool-call":{"identifier":"allow-mcp-approve-tool-call","description":"Enables the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_approve_tool_call"],"deny":[]}},"allow-mcp-call-tool":{"identifier":"allow-mcp-call-tool","description":"Enables the mcp_call_tool command without any pre-configured scope.","commands":{"allow":["mcp_call_tool"],"deny":[]}},"allow-mcp-connect-server":{"identifier":"allow-mcp-connect-server","description":"Enables the mcp_connect_server command without any pre-configured scope.","commands":{"allow":["mcp_connect_server"],"deny":[]}},"allow-mcp-deny-tool-call":{"identifier":"allow-mcp-deny-tool-call","description":"Enables the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":["mcp_deny_tool_call"],"deny":[]}},"allow-mcp-disconnect-server":{"identifier":"allow-mcp-disconnect-server","description":"Enables the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":["mcp_disconnect_server"],"deny":[]}},"allow-mcp-list-permissions":{"identifier":"allow-mcp-list-permissions","description":"Enables the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":["mcp_list_permissions"],"deny":[]}},"allow-mcp-list-servers":{"identifier":"allow-mcp-list-servers","description":"Enables the mcp_list_servers command without any pre-configured scope.","commands":{"allow":["mcp_list_servers"],"deny":[]}},"allow-mcp-list-tools":{"identifier":"allow-mcp-list-tools","description":"Enables the mcp_list_tools command without any pre-configured scope.","commands":{"allow":["mcp_list_tools"],"deny":[]}},"allow-mcp-remove-server-config":{"identifier":"allow-mcp-remove-server-config","description":"Enables the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":["mcp_remove_server_config"],"deny":[]}},"allow-mcp-reset-permission":{"identifier":"allow-mcp-reset-permission","description":"Enables the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":["mcp_reset_permission"],"deny":[]}},"allow-mcp-restart-server":{"identifier":"allow-mcp-restart-server","description":"Enables the mcp_restart_server command without any pre-configured scope.","commands":{"allow":["mcp_restart_server"],"deny":[]}},"allow-pin-session":{"identifier":"allow-pin-session","description":"Enables the pin_session command without any pre-configured scope.","commands":{"allow":["pin_session"],"deny":[]}},"allow-record-directory-usage":{"identifier":"allow-record-directory-usage","description":"Enables the record_directory_usage command without any pre-configured scope.","commands":{"allow":["record_directory_usage"],"deny":[]}},"allow-regenerate-message":{"identifier":"allow-regenerate-message","description":"Enables the regenerate_message command without any pre-configured scope.","commands":{"allow":["regenerate_message"],"deny":[]}},"allow-remove-recent-directory":{"identifier":"allow-remove-recent-directory","description":"Enables the remove_recent_directory command without any pre-configured scope.","commands":{"allow":["remove_recent_directory"],"deny":[]}},"allow-replace-custom-models":{"identifier":"allow-replace-custom-models","description":"Enables the replace_custom_models command without any pre-configured scope.","commands":{"allow":["replace_custom_models"],"deny":[]}},"allow-resolve-close-request":{"identifier":"allow-resolve-close-request","description":"Enables the resolve_close_request command without any pre-configured scope.","commands":{"allow":["resolve_close_request"],"deny":[]}},"allow-restart-sidecar":{"identifier":"allow-restart-sidecar","description":"Enables the restart_sidecar command without any pre-configured scope.","commands":{"allow":["restart_sidecar"],"deny":[]}},"allow-reveal-router-api-key":{"identifier":"allow-reveal-router-api-key","description":"Enables the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":["reveal_router_api_key"],"deny":[]}},"allow-search-messages":{"identifier":"allow-search-messages","description":"Enables the search_messages command without any pre-configured scope.","commands":{"allow":["search_messages"],"deny":[]}},"allow-search-sessions":{"identifier":"allow-search-sessions","description":"Enables the search_sessions command without any pre-configured scope.","commands":{"allow":["search_sessions"],"deny":[]}},"allow-send-message":{"identifier":"allow-send-message","description":"Enables the send_message command without any pre-configured scope.","commands":{"allow":["send_message"],"deny":[]}},"allow-set-session-group":{"identifier":"allow-set-session-group","description":"Enables the set_session_group command without any pre-configured scope.","commands":{"allow":["set_session_group"],"deny":[]}},"allow-set-setting":{"identifier":"allow-set-setting","description":"Enables the set_setting command without any pre-configured scope.","commands":{"allow":["set_setting"],"deny":[]}},"allow-skills-approve-scan":{"identifier":"allow-skills-approve-scan","description":"Enables the skills_approve_scan command without any pre-configured scope.","commands":{"allow":["skills_approve_scan"],"deny":[]}},"allow-skills-cancel-scan":{"identifier":"allow-skills-cancel-scan","description":"Enables the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":["skills_cancel_scan"],"deny":[]}},"allow-skills-download-remote":{"identifier":"allow-skills-download-remote","description":"Enables the skills_download_remote command without any pre-configured scope.","commands":{"allow":["skills_download_remote"],"deny":[]}},"allow-skills-export-installed":{"identifier":"allow-skills-export-installed","description":"Enables the skills_export_installed command without any pre-configured scope.","commands":{"allow":["skills_export_installed"],"deny":[]}},"allow-skills-export-scan":{"identifier":"allow-skills-export-scan","description":"Enables the skills_export_scan command without any pre-configured scope.","commands":{"allow":["skills_export_scan"],"deny":[]}},"allow-skills-get-activation-view":{"identifier":"allow-skills-get-activation-view","description":"Enables the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":["skills_get_activation_view"],"deny":[]}},"allow-skills-get-finding":{"identifier":"allow-skills-get-finding","description":"Enables the skills_get_finding command without any pre-configured scope.","commands":{"allow":["skills_get_finding"],"deny":[]}},"allow-skills-get-migration-status":{"identifier":"allow-skills-get-migration-status","description":"Enables the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":["skills_get_migration_status"],"deny":[]}},"allow-skills-get-remote-detail":{"identifier":"allow-skills-get-remote-detail","description":"Enables the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":["skills_get_remote_detail"],"deny":[]}},"allow-skills-get-scan-privacy-defaults":{"identifier":"allow-skills-get-scan-privacy-defaults","description":"Enables the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":["skills_get_scan_privacy_defaults"],"deny":[]}},"allow-skills-get-scan-summary":{"identifier":"allow-skills-get-scan-summary","description":"Enables the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":["skills_get_scan_summary"],"deny":[]}},"allow-skills-get-summary":{"identifier":"allow-skills-get-summary","description":"Enables the skills_get_summary command without any pre-configured scope.","commands":{"allow":["skills_get_summary"],"deny":[]}},"allow-skills-import-modelscope":{"identifier":"allow-skills-import-modelscope","description":"Enables the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":["skills_import_modelscope"],"deny":[]}},"allow-skills-inspect-archive":{"identifier":"allow-skills-inspect-archive","description":"Enables the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":["skills_inspect_archive"],"deny":[]}},"allow-skills-install-archive":{"identifier":"allow-skills-install-archive","description":"Enables the skills_install_archive command without any pre-configured scope.","commands":{"allow":["skills_install_archive"],"deny":[]}},"allow-skills-install-remote":{"identifier":"allow-skills-install-remote","description":"Enables the skills_install_remote command without any pre-configured scope.","commands":{"allow":["skills_install_remote"],"deny":[]}},"allow-skills-list-approvals":{"identifier":"allow-skills-list-approvals","description":"Enables the skills_list_approvals command without any pre-configured scope.","commands":{"allow":["skills_list_approvals"],"deny":[]}},"allow-skills-list-files":{"identifier":"allow-skills-list-files","description":"Enables the skills_list_files command without any pre-configured scope.","commands":{"allow":["skills_list_files"],"deny":[]}},"allow-skills-list-findings":{"identifier":"allow-skills-list-findings","description":"Enables the skills_list_findings command without any pre-configured scope.","commands":{"allow":["skills_list_findings"],"deny":[]}},"allow-skills-list-installed":{"identifier":"allow-skills-list-installed","description":"Enables the skills_list_installed command without any pre-configured scope.","commands":{"allow":["skills_list_installed"],"deny":[]}},"allow-skills-read-file":{"identifier":"allow-skills-read-file","description":"Enables the skills_read_file command without any pre-configured scope.","commands":{"allow":["skills_read_file"],"deny":[]}},"allow-skills-reject-scan":{"identifier":"allow-skills-reject-scan","description":"Enables the skills_reject_scan command without any pre-configured scope.","commands":{"allow":["skills_reject_scan"],"deny":[]}},"allow-skills-rescan":{"identifier":"allow-skills-rescan","description":"Enables the skills_rescan command without any pre-configured scope.","commands":{"allow":["skills_rescan"],"deny":[]}},"allow-skills-retry-migration-scan":{"identifier":"allow-skills-retry-migration-scan","description":"Enables the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":["skills_retry_migration_scan"],"deny":[]}},"allow-skills-revoke-approval":{"identifier":"allow-skills-revoke-approval","description":"Enables the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":["skills_revoke_approval"],"deny":[]}},"allow-skills-search-remote":{"identifier":"allow-skills-search-remote","description":"Enables the skills_search_remote command without any pre-configured scope.","commands":{"allow":["skills_search_remote"],"deny":[]}},"allow-skills-set-enabled":{"identifier":"allow-skills-set-enabled","description":"Enables the skills_set_enabled command without any pre-configured scope.","commands":{"allow":["skills_set_enabled"],"deny":[]}},"allow-skills-uninstall":{"identifier":"allow-skills-uninstall","description":"Enables the skills_uninstall command without any pre-configured scope.","commands":{"allow":["skills_uninstall"],"deny":[]}},"allow-stop-generation":{"identifier":"allow-stop-generation","description":"Enables the stop_generation command without any pre-configured scope.","commands":{"allow":["stop_generation"],"deny":[]}},"allow-terminal-get-state":{"identifier":"allow-terminal-get-state","description":"Enables the terminal_get_state command without any pre-configured scope.","commands":{"allow":["terminal_get_state"],"deny":[]}},"allow-terminal-kill":{"identifier":"allow-terminal-kill","description":"Enables the terminal_kill command without any pre-configured scope.","commands":{"allow":["terminal_kill"],"deny":[]}},"allow-terminal-resize":{"identifier":"allow-terminal-resize","description":"Enables the terminal_resize command without any pre-configured scope.","commands":{"allow":["terminal_resize"],"deny":[]}},"allow-terminal-spawn":{"identifier":"allow-terminal-spawn","description":"Enables the terminal_spawn command without any pre-configured scope.","commands":{"allow":["terminal_spawn"],"deny":[]}},"allow-terminal-write":{"identifier":"allow-terminal-write","description":"Enables the terminal_write command without any pre-configured scope.","commands":{"allow":["terminal_write"],"deny":[]}},"allow-test-model":{"identifier":"allow-test-model","description":"Enables the test_model command without any pre-configured scope.","commands":{"allow":["test_model"],"deny":[]}},"allow-test-router-connection":{"identifier":"allow-test-router-connection","description":"Enables the test_router_connection command without any pre-configured scope.","commands":{"allow":["test_router_connection"],"deny":[]}},"allow-update-app-config":{"identifier":"allow-update-app-config","description":"Enables the update_app_config command without any pre-configured scope.","commands":{"allow":["update_app_config"],"deny":[]}},"allow-update-router-config":{"identifier":"allow-update-router-config","description":"Enables the update_router_config command without any pre-configured scope.","commands":{"allow":["update_router_config"],"deny":[]}},"allow-update-session":{"identifier":"allow-update-session","description":"Enables the update_session command without any pre-configured scope.","commands":{"allow":["update_session"],"deny":[]}},"allow-update-session-working-dir":{"identifier":"allow-update-session-working-dir","description":"Enables the update_session_working_dir command without any pre-configured scope.","commands":{"allow":["update_session_working_dir"],"deny":[]}},"allow-update-setting":{"identifier":"allow-update-setting","description":"Enables the update_setting command without any pre-configured scope.","commands":{"allow":["update_setting"],"deny":[]}},"allow-update-tray-context":{"identifier":"allow-update-tray-context","description":"Enables the update_tray_context command without any pre-configured scope.","commands":{"allow":["update_tray_context"],"deny":[]}},"allow-update-workspace-preference":{"identifier":"allow-update-workspace-preference","description":"Enables the update_workspace_preference command without any pre-configured scope.","commands":{"allow":["update_workspace_preference"],"deny":[]}},"allow-validate-directory":{"identifier":"allow-validate-directory","description":"Enables the validate_directory command without any pre-configured scope.","commands":{"allow":["validate_directory"],"deny":[]}},"allow-workspace-get-context":{"identifier":"allow-workspace-get-context","description":"Enables the workspace_get_context command without any pre-configured scope.","commands":{"allow":["workspace_get_context"],"deny":[]}},"deny-add-custom-model":{"identifier":"deny-add-custom-model","description":"Denies the add_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["add_custom_model"]}},"deny-append-content-block":{"identifier":"deny-append-content-block","description":"Denies the append_content_block command without any pre-configured scope.","commands":{"allow":[],"deny":["append_content_block"]}},"deny-archive-session":{"identifier":"deny-archive-session","description":"Denies the archive_session command without any pre-configured scope.","commands":{"allow":[],"deny":["archive_session"]}},"deny-artifact-delete-or-expire":{"identifier":"deny-artifact-delete-or-expire","description":"Denies the artifact_delete_or_expire command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_delete_or_expire"]}},"deny-artifact-export":{"identifier":"deny-artifact-export","description":"Denies the artifact_export command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_export"]}},"deny-artifact-get-metadata":{"identifier":"deny-artifact-get-metadata","description":"Denies the artifact_get_metadata command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_metadata"]}},"deny-artifact-get-preview":{"identifier":"deny-artifact-get-preview","description":"Denies the artifact_get_preview command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_get_preview"]}},"deny-artifact-read-preview-base64":{"identifier":"deny-artifact-read-preview-base64","description":"Denies the artifact_read_preview_base64 command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_read_preview_base64"]}},"deny-artifact-register":{"identifier":"deny-artifact-register","description":"Denies the artifact_register command without any pre-configured scope.","commands":{"allow":[],"deny":["artifact_register"]}},"deny-backfill-session-workspaces":{"identifier":"deny-backfill-session-workspaces","description":"Denies the backfill_session_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["backfill_session_workspaces"]}},"deny-browse-directory":{"identifier":"deny-browse-directory","description":"Denies the browse_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["browse_directory"]}},"deny-chart-export-csv":{"identifier":"deny-chart-export-csv","description":"Denies the chart_export_csv command without any pre-configured scope.","commands":{"allow":[],"deny":["chart_export_csv"]}},"deny-create-router-config":{"identifier":"deny-create-router-config","description":"Denies the create_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config"]}},"deny-create-router-config-with-models":{"identifier":"deny-create-router-config-with-models","description":"Denies the create_router_config_with_models command without any pre-configured scope.","commands":{"allow":[],"deny":["create_router_config_with_models"]}},"deny-create-session":{"identifier":"deny-create-session","description":"Denies the create_session command without any pre-configured scope.","commands":{"allow":[],"deny":["create_session"]}},"deny-delete-custom-model":{"identifier":"deny-delete-custom-model","description":"Denies the delete_custom_model command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_custom_model"]}},"deny-delete-router-config":{"identifier":"deny-delete-router-config","description":"Denies the delete_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_router_config"]}},"deny-delete-session":{"identifier":"deny-delete-session","description":"Denies the delete_session command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_session"]}},"deny-export-sessions":{"identifier":"deny-export-sessions","description":"Denies the export_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["export_sessions"]}},"deny-fetch-provider-models":{"identifier":"deny-fetch-provider-models","description":"Denies the fetch_provider_models command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_provider_models"]}},"deny-fs-list-dir":{"identifier":"deny-fs-list-dir","description":"Denies the fs_list_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_list_dir"]}},"deny-fs-read-text-file":{"identifier":"deny-fs-read-text-file","description":"Denies the fs_read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_read_text_file"]}},"deny-fs-reveal-in-explorer":{"identifier":"deny-fs-reveal-in-explorer","description":"Denies the fs_reveal_in_explorer command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_reveal_in_explorer"]}},"deny-fs-write-text-file":{"identifier":"deny-fs-write-text-file","description":"Denies the fs_write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["fs_write_text_file"]}},"deny-generate-session-title":{"identifier":"deny-generate-session-title","description":"Denies the generate_session_title command without any pre-configured scope.","commands":{"allow":[],"deny":["generate_session_title"]}},"deny-get-all-settings":{"identifier":"deny-get-all-settings","description":"Denies the get_all_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_settings"]}},"deny-get-app-config":{"identifier":"deny-get-app-config","description":"Denies the get_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["get_app_config"]}},"deny-get-message-blocks":{"identifier":"deny-get-message-blocks","description":"Denies the get_message_blocks command without any pre-configured scope.","commands":{"allow":[],"deny":["get_message_blocks"]}},"deny-get-messages":{"identifier":"deny-get-messages","description":"Denies the get_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["get_messages"]}},"deny-get-recent-directories":{"identifier":"deny-get-recent-directories","description":"Denies the get_recent_directories command without any pre-configured scope.","commands":{"allow":[],"deny":["get_recent_directories"]}},"deny-get-session":{"identifier":"deny-get-session","description":"Denies the get_session command without any pre-configured scope.","commands":{"allow":[],"deny":["get_session"]}},"deny-get-setting":{"identifier":"deny-get-setting","description":"Denies the get_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["get_setting"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-get-sidecar-status":{"identifier":"deny-get-sidecar-status","description":"Denies the get_sidecar_status command without any pre-configured scope.","commands":{"allow":[],"deny":["get_sidecar_status"]}},"deny-get-system-info":{"identifier":"deny-get-system-info","description":"Denies the get_system_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_system_info"]}},"deny-import-sessions":{"identifier":"deny-import-sessions","description":"Denies the import_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["import_sessions"]}},"deny-list-available-models":{"identifier":"deny-list-available-models","description":"Denies the list_available_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_available_models"]}},"deny-list-custom-models":{"identifier":"deny-list-custom-models","description":"Denies the list_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["list_custom_models"]}},"deny-list-router-configs":{"identifier":"deny-list-router-configs","description":"Denies the list_router_configs command without any pre-configured scope.","commands":{"allow":[],"deny":["list_router_configs"]}},"deny-list-session-groups":{"identifier":"deny-list-session-groups","description":"Denies the list_session_groups command without any pre-configured scope.","commands":{"allow":[],"deny":["list_session_groups"]}},"deny-list-sessions":{"identifier":"deny-list-sessions","description":"Denies the list_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["list_sessions"]}},"deny-list-workspace-preferences":{"identifier":"deny-list-workspace-preferences","description":"Denies the list_workspace_preferences command without any pre-configured scope.","commands":{"allow":[],"deny":["list_workspace_preferences"]}},"deny-map-export-geojson":{"identifier":"deny-map-export-geojson","description":"Denies the map_export_geojson command without any pre-configured scope.","commands":{"allow":[],"deny":["map_export_geojson"]}},"deny-mcp-add-server-config":{"identifier":"deny-mcp-add-server-config","description":"Denies the mcp_add_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_add_server_config"]}},"deny-mcp-approve-tool-call":{"identifier":"deny-mcp-approve-tool-call","description":"Denies the mcp_approve_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_approve_tool_call"]}},"deny-mcp-call-tool":{"identifier":"deny-mcp-call-tool","description":"Denies the mcp_call_tool command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_call_tool"]}},"deny-mcp-connect-server":{"identifier":"deny-mcp-connect-server","description":"Denies the mcp_connect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_connect_server"]}},"deny-mcp-deny-tool-call":{"identifier":"deny-mcp-deny-tool-call","description":"Denies the mcp_deny_tool_call command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_deny_tool_call"]}},"deny-mcp-disconnect-server":{"identifier":"deny-mcp-disconnect-server","description":"Denies the mcp_disconnect_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_disconnect_server"]}},"deny-mcp-list-permissions":{"identifier":"deny-mcp-list-permissions","description":"Denies the mcp_list_permissions command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_permissions"]}},"deny-mcp-list-servers":{"identifier":"deny-mcp-list-servers","description":"Denies the mcp_list_servers command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_servers"]}},"deny-mcp-list-tools":{"identifier":"deny-mcp-list-tools","description":"Denies the mcp_list_tools command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_list_tools"]}},"deny-mcp-remove-server-config":{"identifier":"deny-mcp-remove-server-config","description":"Denies the mcp_remove_server_config command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_remove_server_config"]}},"deny-mcp-reset-permission":{"identifier":"deny-mcp-reset-permission","description":"Denies the mcp_reset_permission command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_reset_permission"]}},"deny-mcp-restart-server":{"identifier":"deny-mcp-restart-server","description":"Denies the mcp_restart_server command without any pre-configured scope.","commands":{"allow":[],"deny":["mcp_restart_server"]}},"deny-pin-session":{"identifier":"deny-pin-session","description":"Denies the pin_session command without any pre-configured scope.","commands":{"allow":[],"deny":["pin_session"]}},"deny-record-directory-usage":{"identifier":"deny-record-directory-usage","description":"Denies the record_directory_usage command without any pre-configured scope.","commands":{"allow":[],"deny":["record_directory_usage"]}},"deny-regenerate-message":{"identifier":"deny-regenerate-message","description":"Denies the regenerate_message command without any pre-configured scope.","commands":{"allow":[],"deny":["regenerate_message"]}},"deny-remove-recent-directory":{"identifier":"deny-remove-recent-directory","description":"Denies the remove_recent_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_recent_directory"]}},"deny-replace-custom-models":{"identifier":"deny-replace-custom-models","description":"Denies the replace_custom_models command without any pre-configured scope.","commands":{"allow":[],"deny":["replace_custom_models"]}},"deny-resolve-close-request":{"identifier":"deny-resolve-close-request","description":"Denies the resolve_close_request command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_close_request"]}},"deny-restart-sidecar":{"identifier":"deny-restart-sidecar","description":"Denies the restart_sidecar command without any pre-configured scope.","commands":{"allow":[],"deny":["restart_sidecar"]}},"deny-reveal-router-api-key":{"identifier":"deny-reveal-router-api-key","description":"Denies the reveal_router_api_key command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_router_api_key"]}},"deny-search-messages":{"identifier":"deny-search-messages","description":"Denies the search_messages command without any pre-configured scope.","commands":{"allow":[],"deny":["search_messages"]}},"deny-search-sessions":{"identifier":"deny-search-sessions","description":"Denies the search_sessions command without any pre-configured scope.","commands":{"allow":[],"deny":["search_sessions"]}},"deny-send-message":{"identifier":"deny-send-message","description":"Denies the send_message command without any pre-configured scope.","commands":{"allow":[],"deny":["send_message"]}},"deny-set-session-group":{"identifier":"deny-set-session-group","description":"Denies the set_session_group command without any pre-configured scope.","commands":{"allow":[],"deny":["set_session_group"]}},"deny-set-setting":{"identifier":"deny-set-setting","description":"Denies the set_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["set_setting"]}},"deny-skills-approve-scan":{"identifier":"deny-skills-approve-scan","description":"Denies the skills_approve_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_approve_scan"]}},"deny-skills-cancel-scan":{"identifier":"deny-skills-cancel-scan","description":"Denies the skills_cancel_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_cancel_scan"]}},"deny-skills-download-remote":{"identifier":"deny-skills-download-remote","description":"Denies the skills_download_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_download_remote"]}},"deny-skills-export-installed":{"identifier":"deny-skills-export-installed","description":"Denies the skills_export_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_installed"]}},"deny-skills-export-scan":{"identifier":"deny-skills-export-scan","description":"Denies the skills_export_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_export_scan"]}},"deny-skills-get-activation-view":{"identifier":"deny-skills-get-activation-view","description":"Denies the skills_get_activation_view command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_activation_view"]}},"deny-skills-get-finding":{"identifier":"deny-skills-get-finding","description":"Denies the skills_get_finding command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_finding"]}},"deny-skills-get-migration-status":{"identifier":"deny-skills-get-migration-status","description":"Denies the skills_get_migration_status command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_migration_status"]}},"deny-skills-get-remote-detail":{"identifier":"deny-skills-get-remote-detail","description":"Denies the skills_get_remote_detail command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_remote_detail"]}},"deny-skills-get-scan-privacy-defaults":{"identifier":"deny-skills-get-scan-privacy-defaults","description":"Denies the skills_get_scan_privacy_defaults command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_privacy_defaults"]}},"deny-skills-get-scan-summary":{"identifier":"deny-skills-get-scan-summary","description":"Denies the skills_get_scan_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_scan_summary"]}},"deny-skills-get-summary":{"identifier":"deny-skills-get-summary","description":"Denies the skills_get_summary command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_get_summary"]}},"deny-skills-import-modelscope":{"identifier":"deny-skills-import-modelscope","description":"Denies the skills_import_modelscope command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_import_modelscope"]}},"deny-skills-inspect-archive":{"identifier":"deny-skills-inspect-archive","description":"Denies the skills_inspect_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_inspect_archive"]}},"deny-skills-install-archive":{"identifier":"deny-skills-install-archive","description":"Denies the skills_install_archive command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_archive"]}},"deny-skills-install-remote":{"identifier":"deny-skills-install-remote","description":"Denies the skills_install_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_install_remote"]}},"deny-skills-list-approvals":{"identifier":"deny-skills-list-approvals","description":"Denies the skills_list_approvals command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_approvals"]}},"deny-skills-list-files":{"identifier":"deny-skills-list-files","description":"Denies the skills_list_files command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_files"]}},"deny-skills-list-findings":{"identifier":"deny-skills-list-findings","description":"Denies the skills_list_findings command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_findings"]}},"deny-skills-list-installed":{"identifier":"deny-skills-list-installed","description":"Denies the skills_list_installed command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_list_installed"]}},"deny-skills-read-file":{"identifier":"deny-skills-read-file","description":"Denies the skills_read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_read_file"]}},"deny-skills-reject-scan":{"identifier":"deny-skills-reject-scan","description":"Denies the skills_reject_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_reject_scan"]}},"deny-skills-rescan":{"identifier":"deny-skills-rescan","description":"Denies the skills_rescan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_rescan"]}},"deny-skills-retry-migration-scan":{"identifier":"deny-skills-retry-migration-scan","description":"Denies the skills_retry_migration_scan command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_retry_migration_scan"]}},"deny-skills-revoke-approval":{"identifier":"deny-skills-revoke-approval","description":"Denies the skills_revoke_approval command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_revoke_approval"]}},"deny-skills-search-remote":{"identifier":"deny-skills-search-remote","description":"Denies the skills_search_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_search_remote"]}},"deny-skills-set-enabled":{"identifier":"deny-skills-set-enabled","description":"Denies the skills_set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_set_enabled"]}},"deny-skills-uninstall":{"identifier":"deny-skills-uninstall","description":"Denies the skills_uninstall command without any pre-configured scope.","commands":{"allow":[],"deny":["skills_uninstall"]}},"deny-stop-generation":{"identifier":"deny-stop-generation","description":"Denies the stop_generation command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_generation"]}},"deny-terminal-get-state":{"identifier":"deny-terminal-get-state","description":"Denies the terminal_get_state command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_get_state"]}},"deny-terminal-kill":{"identifier":"deny-terminal-kill","description":"Denies the terminal_kill command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_kill"]}},"deny-terminal-resize":{"identifier":"deny-terminal-resize","description":"Denies the terminal_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_resize"]}},"deny-terminal-spawn":{"identifier":"deny-terminal-spawn","description":"Denies the terminal_spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_spawn"]}},"deny-terminal-write":{"identifier":"deny-terminal-write","description":"Denies the terminal_write command without any pre-configured scope.","commands":{"allow":[],"deny":["terminal_write"]}},"deny-test-model":{"identifier":"deny-test-model","description":"Denies the test_model command without any pre-configured scope.","commands":{"allow":[],"deny":["test_model"]}},"deny-test-router-connection":{"identifier":"deny-test-router-connection","description":"Denies the test_router_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["test_router_connection"]}},"deny-update-app-config":{"identifier":"deny-update-app-config","description":"Denies the update_app_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_app_config"]}},"deny-update-router-config":{"identifier":"deny-update-router-config","description":"Denies the update_router_config command without any pre-configured scope.","commands":{"allow":[],"deny":["update_router_config"]}},"deny-update-session":{"identifier":"deny-update-session","description":"Denies the update_session command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session"]}},"deny-update-session-working-dir":{"identifier":"deny-update-session-working-dir","description":"Denies the update_session_working_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["update_session_working_dir"]}},"deny-update-setting":{"identifier":"deny-update-setting","description":"Denies the update_setting command without any pre-configured scope.","commands":{"allow":[],"deny":["update_setting"]}},"deny-update-tray-context":{"identifier":"deny-update-tray-context","description":"Denies the update_tray_context command without any pre-configured scope.","commands":{"allow":[],"deny":["update_tray_context"]}},"deny-update-workspace-preference":{"identifier":"deny-update-workspace-preference","description":"Denies the update_workspace_preference command without any pre-configured scope.","commands":{"allow":[],"deny":["update_workspace_preference"]}},"deny-validate-directory":{"identifier":"deny-validate-directory","description":"Denies the validate_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["validate_directory"]}},"deny-workspace-get-context":{"identifier":"deny-workspace-get-context","description":"Denies the workspace_get_context command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_get_context"]}},"main-commands":{"identifier":"main-commands","description":"Allows the main bundled UI to call MisakaX application commands other than Workspace Terminal runtime commands.","commands":{"allow":["get_settings","update_setting","get_app_config","update_app_config","get_setting","set_setting","get_all_settings","get_system_info","update_tray_context","resolve_close_request","list_router_configs","create_router_config","create_router_config_with_models","update_router_config","delete_router_config","reveal_router_api_key","test_router_connection","list_available_models","list_custom_models","add_custom_model","replace_custom_models","delete_custom_model","fetch_provider_models","test_model","send_message","stop_generation","regenerate_message","generate_session_title","get_messages","fs_list_dir","fs_read_text_file","fs_write_text_file","fs_reveal_in_explorer","browse_directory","validate_directory","get_recent_directories","record_directory_usage","remove_recent_directory","list_workspace_preferences","update_workspace_preference","workspace_get_context","create_session","list_sessions","update_session","delete_session","search_sessions","update_session_working_dir","get_session","pin_session","archive_session","set_session_group","list_session_groups","search_messages","export_sessions","import_sessions","backfill_session_workspaces","get_sidecar_status","restart_sidecar","mcp_list_servers","mcp_connect_server","mcp_disconnect_server","mcp_restart_server","mcp_list_tools","mcp_call_tool","mcp_add_server_config","mcp_remove_server_config","mcp_approve_tool_call","mcp_deny_tool_call","mcp_list_permissions","mcp_reset_permission","skills_list_installed","skills_get_activation_view","skills_get_summary","skills_list_files","skills_read_file","skills_get_scan_summary","skills_list_findings","skills_get_finding","skills_list_approvals","skills_rescan","skills_cancel_scan","skills_approve_scan","skills_reject_scan","skills_revoke_approval","skills_export_scan","skills_get_scan_privacy_defaults","skills_get_migration_status","skills_retry_migration_scan","skills_inspect_archive","skills_install_archive","skills_search_remote","skills_get_remote_detail","skills_install_remote","skills_import_modelscope","skills_export_installed","skills_download_remote","skills_set_enabled","skills_uninstall","artifact_register","artifact_get_metadata","artifact_get_preview","artifact_read_preview_base64","artifact_export","artifact_delete_or_expire","append_content_block","get_message_blocks","chart_export_csv","map_export_geojson"],"deny":[]}},"terminal-runtime":{"identifier":"terminal-runtime","description":"Allows the main bundled UI to control only owner-bound Workspace Terminal sessions.","commands":{"allow":["terminal_spawn","terminal_write","terminal_resize","terminal_kill","terminal_get_state"],"deny":[]}}},"permission_sets":{},"global_scope_schema":null},"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `allow-message` and will be removed in v3)","commands":{"allow":["message"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope. (**DEPRECATED**: This is now an alias to `deny-message` and will be removed in v3)","commands":{"allow":[],"deny":["message"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality with a reasonable\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 0bce8f7..62d088e 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -638,6 +638,12 @@ "const": "allow-list-workspace-preferences", "markdownDescription": "Enables the list_workspace_preferences command without any pre-configured scope." }, + { + "description": "Enables the map_export_geojson command without any pre-configured scope.", + "type": "string", + "const": "allow-map-export-geojson", + "markdownDescription": "Enables the map_export_geojson command without any pre-configured scope." + }, { "description": "Enables the mcp_add_server_config command without any pre-configured scope.", "type": "string", @@ -1310,6 +1316,12 @@ "const": "deny-list-workspace-preferences", "markdownDescription": "Denies the list_workspace_preferences command without any pre-configured scope." }, + { + "description": "Denies the map_export_geojson command without any pre-configured scope.", + "type": "string", + "const": "deny-map-export-geojson", + "markdownDescription": "Denies the map_export_geojson command without any pre-configured scope." + }, { "description": "Denies the mcp_add_server_config command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/gen/schemas/windows-schema.json b/src-tauri/gen/schemas/windows-schema.json index 0bce8f7..62d088e 100644 --- a/src-tauri/gen/schemas/windows-schema.json +++ b/src-tauri/gen/schemas/windows-schema.json @@ -638,6 +638,12 @@ "const": "allow-list-workspace-preferences", "markdownDescription": "Enables the list_workspace_preferences command without any pre-configured scope." }, + { + "description": "Enables the map_export_geojson command without any pre-configured scope.", + "type": "string", + "const": "allow-map-export-geojson", + "markdownDescription": "Enables the map_export_geojson command without any pre-configured scope." + }, { "description": "Enables the mcp_add_server_config command without any pre-configured scope.", "type": "string", @@ -1310,6 +1316,12 @@ "const": "deny-list-workspace-preferences", "markdownDescription": "Denies the list_workspace_preferences command without any pre-configured scope." }, + { + "description": "Denies the map_export_geojson command without any pre-configured scope.", + "type": "string", + "const": "deny-map-export-geojson", + "markdownDescription": "Denies the map_export_geojson command without any pre-configured scope." + }, { "description": "Denies the mcp_add_server_config command without any pre-configured scope.", "type": "string", diff --git a/src-tauri/permissions/main.toml b/src-tauri/permissions/main.toml index cb2204d..d30b072 100644 --- a/src-tauri/permissions/main.toml +++ b/src-tauri/permissions/main.toml @@ -109,4 +109,5 @@ commands.allow = [ "append_content_block", "get_message_blocks", "chart_export_csv", + "map_export_geojson", ] diff --git a/src-tauri/src/commands/map.rs b/src-tauri/src/commands/map.rs new file mode 100644 index 0000000..5c8192e --- /dev/null +++ b/src-tauri/src/commands/map.rs @@ -0,0 +1,91 @@ +use rusqlite::params; +use tauri::State; + +use crate::config; +use crate::services::artifacts::{ + ArtifactMetadata, ArtifactOrigin, ArtifactService, ContentSafetyPolicy, +}; +use crate::services::content::MapSpecV1; +use crate::AppState; + +fn service() -> Result { + ArtifactService::new( + config::artifacts_dir().map_err(|error| error.to_string())?, + ContentSafetyPolicy::default(), + ) + .map_err(|error| error.to_string()) +} + +#[tauri::command] +pub fn map_export_geojson( + state: State<'_, AppState>, + session_id: String, + message_id: String, + spec: MapSpecV1, +) -> Result { + if !state.feature_flags.rich_content_write { + return Err("CONTENT_BLOCK_UNSUPPORTED".to_string()); + } + + let service = service()?; + spec.validate(service.policy()) + .map_err(|error| error.to_string())?; + + let conn = state.db.lock().map_err(|error| error.to_string())?; + let message_belongs_to_session = conn + .query_row( + "SELECT EXISTS(SELECT 1 FROM messages WHERE id = ?1 AND session_id = ?2)", + params![message_id, session_id], + |row| row.get::<_, bool>(0), + ) + .map_err(|error| error.to_string())?; + if !message_belongs_to_session { + return Err("ARTIFACT_ACCESS_DENIED".to_string()); + } + + service + .register_bytes( + &conn, + session_id, + Some(message_id), + ArtifactOrigin::Agent, + "map-data.geojson".to_string(), + "application/geo+json".to_string(), + &map_geojson(&spec)?, + ) + .map_err(|error| error.to_string()) +} + +fn map_geojson(spec: &MapSpecV1) -> Result, String> { + serde_json::to_vec(&spec.feature_collection).map_err(|_| "MAP_SPEC_INVALID".to_string()) +} + +#[cfg(test)] +mod tests { + use super::{map_geojson, MapSpecV1}; + + #[test] + fn geojson_export_contains_only_the_feature_collection() { + let spec: MapSpecV1 = serde_json::from_value(serde_json::json!({ + "title": "Places", + "feature_collection": { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "geometry": { "type": "Point", "coordinates": [120.0, 30.0] }, + "properties": { "name": "Hangzhou" } + }] + }, + "markers": [{ "longitude": 120.0, "latitude": 30.0, "label": "Hangzhou" }], + "tile_source_id": "must-not-be-exported" + })) + .unwrap(); + + let geojson: serde_json::Value = + serde_json::from_slice(&map_geojson(&spec).unwrap()).unwrap(); + assert_eq!(geojson["type"], "FeatureCollection"); + assert_eq!(geojson["features"][0]["properties"]["name"], "Hangzhou"); + assert!(geojson.get("markers").is_none()); + assert!(geojson.get("tile_source_id").is_none()); + } +} diff --git a/src-tauri/src/commands/mod.rs b/src-tauri/src/commands/mod.rs index e1f0918..3406be5 100644 --- a/src-tauri/src/commands/mod.rs +++ b/src-tauri/src/commands/mod.rs @@ -2,6 +2,7 @@ pub mod artifacts; pub mod chart; pub mod chat; pub mod fs_explorer; +pub mod map; pub mod mcp; pub mod models; pub mod router_configs; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7069567..bc2b470 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -160,6 +160,7 @@ pub fn run() { commands::artifacts::append_content_block, commands::artifacts::get_message_blocks, commands::chart::chart_export_csv, + commands::map::map_export_geojson, commands::fs_explorer::fs_list_dir, commands::fs_explorer::fs_read_text_file, commands::fs_explorer::fs_write_text_file, diff --git a/src-tauri/src/services/artifacts/service.rs b/src-tauri/src/services/artifacts/service.rs index a5eff7a..c05d4de 100644 --- a/src-tauri/src/services/artifacts/service.rs +++ b/src-tauri/src/services/artifacts/service.rs @@ -377,7 +377,11 @@ fn detect_media_type(bytes: &[u8], declared: &str) -> Result { } } else if is_safe_text(bytes) { match declared.as_str() { - "text/plain" | "text/markdown" | "application/json" | "text/csv" => declared.as_str(), + "text/plain" + | "text/markdown" + | "application/json" + | "application/geo+json" + | "text/csv" => declared.as_str(), _ => "text/plain", } } else { @@ -557,6 +561,18 @@ mod tests { .is_err()); } + #[test] + fn preserves_safe_geojson_media_type() { + assert_eq!( + detect_media_type( + br#"{"type":"FeatureCollection","features":[]}"#, + "application/geo+json", + ) + .unwrap(), + "application/geo+json" + ); + } + #[test] fn rejects_an_oversized_pixel_header_before_preview() { let temp = tempfile::tempdir().unwrap(); diff --git a/src/__tests__/rich-content-map.test.ts b/src/__tests__/rich-content-map.test.ts new file mode 100644 index 0000000..e0c2f32 --- /dev/null +++ b/src/__tests__/rich-content-map.test.ts @@ -0,0 +1,57 @@ +import { describe, expect, it } from "vitest"; +import type { ContentBlock } from "@/lib/ipc"; +import { readMapSpec } from "@/features/chat-content/renderers/map-types"; + +function mapBlock(spec: unknown): ContentBlock { + return { + id: "block-1", + message_id: "message-1", + position: 0, + schema_version: 1, + kind: "map", + status: "ready", + payload: { spec }, + fallback: { title: "Map", message_key: "richContent.blockUnavailable" }, + generation: 1, + revision: 1, + created_at: "2026-08-09T00:00:00Z", + updated_at: "2026-08-09T00:00:00Z", + }; +} + +const validSpec = { + title: "Hangzhou places", + feature_collection: { + type: "FeatureCollection", + features: [{ + type: "Feature", + geometry: { type: "Point", coordinates: [120.15, 30.28] }, + properties: { name: "West Lake" }, + }], + }, + markers: [{ longitude: 120.15, latitude: 30.28, label: "West Lake" }], +}; + +describe("local rich-content map parser", () => { + it("accepts bounded local GeoJSON without a remote resource", () => { + expect(readMapSpec(mapBlock(validSpec))).toMatchObject({ + title: "Hangzhou places", + feature_collection: { type: "FeatureCollection" }, + markers: [{ label: "West Lake" }], + }); + }); + + it("rejects remote tile configuration and invalid coordinates", () => { + expect(readMapSpec(mapBlock({ ...validSpec, tile_source_id: "https://tiles.example.com/{z}/{x}/{y}" }))).toBeNull(); + expect(readMapSpec(mapBlock({ + ...validSpec, + feature_collection: { + ...validSpec.feature_collection, + features: [{ + ...validSpec.feature_collection.features[0], + geometry: { type: "Point", coordinates: [120.15, 91] }, + }], + }, + }))).toBeNull(); + }); +}); diff --git a/src/features/chat-content/RichContentCard.tsx b/src/features/chat-content/RichContentCard.tsx index dd2c2bf..660da32 100644 --- a/src/features/chat-content/RichContentCard.tsx +++ b/src/features/chat-content/RichContentCard.tsx @@ -4,6 +4,7 @@ import { cn } from "@/lib/utils"; interface RichContentCardProps { title: string; + meta?: ReactNode; icon: ReactNode; status?: "pending" | "failed" | "unsupported" | "ready"; actions?: ReactNode; @@ -14,6 +15,7 @@ interface RichContentCardProps { export function RichContentCard({ title, + meta, icon, status = "ready", actions, @@ -35,6 +37,7 @@ export function RichContentCard({ {icon}

{title}

+ {meta ? {meta} : null} {status === "pending" ? ( ) : null} diff --git a/src/features/chat-content/renderer-registry.tsx b/src/features/chat-content/renderer-registry.tsx index 6e3e065..36c839e 100644 --- a/src/features/chat-content/renderer-registry.tsx +++ b/src/features/chat-content/renderer-registry.tsx @@ -4,6 +4,7 @@ import type { ContentBlock } from "@/lib/ipc"; import { ArtifactBlockRenderer } from "./renderers/ArtifactBlockRenderer"; import { ChartBlockRenderer } from "./renderers/ChartBlockRenderer"; import { ImageBlockRenderer } from "./renderers/ImageBlockRenderer"; +import { MapBlockRenderer } from "./renderers/MapBlockRenderer"; import { MarkdownBlockRenderer } from "./renderers/MarkdownBlockRenderer"; import { NoticeBlockRenderer } from "./renderers/NoticeBlockRenderer"; @@ -16,7 +17,7 @@ export interface BlockRendererProps { const REGISTRY: Record> = { markdown: MarkdownBlockRenderer, chart: ChartBlockRenderer, - map: NoticeBlockRenderer, + map: MapBlockRenderer, artifact: ArtifactBlockRenderer, image: ImageBlockRenderer, notice: NoticeBlockRenderer, diff --git a/src/features/chat-content/renderers/MapBlockRenderer.tsx b/src/features/chat-content/renderers/MapBlockRenderer.tsx new file mode 100644 index 0000000..2b8b7cc --- /dev/null +++ b/src/features/chat-content/renderers/MapBlockRenderer.tsx @@ -0,0 +1,184 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { Copy, Download, List, LoaderCircle, MapPinned, RotateCcw } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; +import { Button } from "@/components/ui/button"; +import { artifactsIpc } from "@/lib/ipc"; +import type { Map as MapLibreMap, StyleSpecification } from "maplibre-gl"; +import type { BlockRendererProps } from "../renderer-registry"; +import { RichContentCard } from "../RichContentCard"; +import { readMapSpec, type MapSpecV1 } from "./map-types"; +import { NoticeBlockRenderer } from "./NoticeBlockRenderer"; + +const LOCAL_MAP_STYLE: StyleSpecification = { + version: 8, + sources: {}, + layers: [{ id: "background", type: "background", paint: { "background-color": "#18181b" } }], +}; + +export function MapBlockRenderer({ block, sessionId }: BlockRendererProps) { + const { t } = useTranslation("chat"); + const spec = useMemo(() => readMapSpec(block), [block]); + const [showFeatures, setShowFeatures] = useState(false); + const [resetNonce, setResetNonce] = useState(0); + const [exporting, setExporting] = useState(false); + const [copied, setCopied] = useState(false); + const [error, setError] = useState(null); + const coordinates = useMemo(() => JSON.stringify(spec?.feature_collection ?? {}, null, 2), [spec]); + + const copyCoordinates = useCallback(() => { + void writeText(coordinates).then(() => { + setCopied(true); + window.setTimeout(() => setCopied(false), 1600); + }).catch(() => setError(t("richContent.map.copyFailed"))); + }, [coordinates, t]); + + const exportGeojson = useCallback(async () => { + if (!spec) return; + setExporting(true); + setError(null); + let artifactId: string | null = null; + try { + const metadata = await artifactsIpc.exportMapGeojson(sessionId, block.message_id, spec); + artifactId = metadata.artifact_id; + await artifactsIpc.export(sessionId, metadata.artifact_id); + } catch { + setError(t("richContent.map.exportFailed")); + } finally { + if (artifactId) void artifactsIpc.expire(sessionId, artifactId); + setExporting(false); + } + }, [block.message_id, sessionId, spec, t]); + + if (!spec) return ; + return ( + } + status={block.status} + actions={ + <> + + + {spec.initial_view || spec.bounds || spec.markers.length > 0 ? ( + + ) : null} + + + } + footer={error ? {error} : copied ? t("richContent.map.copied") : null} + > + + {showFeatures ? : null} + + ); +} + +function LocalMap({ spec }: { spec: MapSpecV1 }) { + const { t } = useTranslation("chat"); + const elementRef = useRef(null); + const [unavailable, setUnavailable] = useState(false); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const element = elementRef.current; + if (!element) return; + setUnavailable(false); + setLoading(true); + let disposed = false; + let map: MapLibreMap | null = null; + let resizeObserver: ResizeObserver | null = null; + void (async () => { + try { + await import("maplibre-gl/dist/maplibre-gl.css"); + const maplibre = await import("maplibre-gl"); + if (disposed) return; + const firstMarker = spec.markers?.[0]; + const initialView = spec.initial_view; + const richMap = new maplibre.Map({ + container: element, + style: LOCAL_MAP_STYLE, + center: initialView + ? [initialView.longitude, initialView.latitude] + : firstMarker ? [firstMarker.longitude, firstMarker.latitude] : [0, 0], + zoom: initialView?.zoom ?? (firstMarker ? 5 : 1), + attributionControl: false, + }); + map = richMap; + resizeObserver = new ResizeObserver(() => richMap.resize()); + resizeObserver.observe(element); + richMap.on("load", () => { + if (disposed) return; + setLoading(false); + richMap.addSource("rich-content-data", { type: "geojson", data: spec.feature_collection as never }); + richMap.addLayer({ id: "rich-content-fill", type: "fill", source: "rich-content-data", paint: { "fill-color": "#a1a1aa", "fill-opacity": 0.16 } }); + richMap.addLayer({ id: "rich-content-line", type: "line", source: "rich-content-data", paint: { "line-color": "#d4d4d8", "line-width": 2 } }); + richMap.addLayer({ id: "rich-content-point", type: "circle", source: "rich-content-data", paint: { "circle-color": "#d4d4d8", "circle-radius": 5 } }); + spec.markers?.forEach((marker) => { + new maplibre.Marker({ color: "#a1a1aa" }) + .setLngLat([marker.longitude, marker.latitude]) + .addTo(richMap); + }); + if (spec.bounds) { + richMap.fitBounds( + [[spec.bounds.west, spec.bounds.south], [spec.bounds.east, spec.bounds.north]], + { padding: 32, maxZoom: 16, duration: 0 }, + ); + } + }); + richMap.on("error", () => { + if (!disposed) { + setLoading(false); + setUnavailable(true); + } + }); + } catch { + if (!disposed) { + setLoading(false); + setUnavailable(true); + } + } + })(); + return () => { + disposed = true; + resizeObserver?.disconnect(); + map?.remove(); + }; + }, [spec]); + + if (unavailable) return ; + return ( +
+
+ {loading ? : null} +
+ ); +} + +function FeatureList({ spec, label }: { spec: MapSpecV1; label?: string }) { + const { t } = useTranslation("chat"); + return ( +
+ {label ?

{label}

: null} +

{t("richContent.map.featureCount", { count: spec.feature_collection.features.length })}

+
    + {spec.feature_collection.features.slice(0, 200).map((feature, index) => ( +
  • + {feature.geometry.type} + {feature.properties && Object.keys(feature.properties).length > 0 ? {Object.entries(feature.properties).map(([key, value]) => `${key}: ${value}`).join(" · ")} : null} +
  • + ))} +
+ {spec.feature_collection.features.length > 200 ?

{t("richContent.map.featureListTruncated", { count: spec.feature_collection.features.length })}

: null} +
+ ); +} diff --git a/src/features/chat-content/renderers/map-types.ts b/src/features/chat-content/renderers/map-types.ts new file mode 100644 index 0000000..4bd4309 --- /dev/null +++ b/src/features/chat-content/renderers/map-types.ts @@ -0,0 +1,164 @@ +import type { ContentBlock } from "@/lib/ipc"; + +export interface GeoJsonFeature { + type: "Feature"; + geometry: { + type: "Point" | "LineString" | "Polygon"; + coordinates: unknown; + }; + properties?: Record; +} + +export interface MapSpecV1 { + title: string; + summary?: string; + feature_collection: { + type: "FeatureCollection"; + features: GeoJsonFeature[]; + }; + markers: Array<{ longitude: number; latitude: number; label: string }>; + attribution?: string; + initial_view?: { longitude: number; latitude: number; zoom: number }; + bounds?: { west: number; south: number; east: number; north: number }; +} + +const MAX_FEATURES = 10_000; +const MAX_PROPERTIES = 24; +const MAX_LABEL_CHARS = 512; + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function isString(value: unknown): value is string { + return typeof value === "string"; +} + +function isCoordinatePair(value: unknown): value is [number, number] { + return Array.isArray(value) + && value.length === 2 + && value.every((coordinate) => typeof coordinate === "number" && Number.isFinite(coordinate)) + && value[0] >= -180 + && value[0] <= 180 + && value[1] >= -90 + && value[1] <= 90; +} + +function areCoordinatesValid(value: unknown): boolean { + if (isCoordinatePair(value)) return true; + return Array.isArray(value) && value.length > 0 && value.every(areCoordinatesValid); +} + +function readView(value: unknown): MapSpecV1["initial_view"] | null { + if ( + !isRecord(value) + || typeof value.longitude !== "number" + || typeof value.latitude !== "number" + || typeof value.zoom !== "number" + || !Number.isFinite(value.zoom) + || value.zoom < 0 + || value.zoom > 22 + || !isCoordinatePair([value.longitude, value.latitude]) + ) { + return null; + } + return { longitude: value.longitude, latitude: value.latitude, zoom: value.zoom }; +} + +function readBounds(value: unknown): MapSpecV1["bounds"] | null { + if ( + !isRecord(value) + || typeof value.west !== "number" + || typeof value.south !== "number" + || typeof value.east !== "number" + || typeof value.north !== "number" + || !isCoordinatePair([value.west, value.south]) + || !isCoordinatePair([value.east, value.north]) + || value.west > value.east + || value.south > value.north + ) { + return null; + } + return { west: value.west, south: value.south, east: value.east, north: value.north }; +} + +export function readMapSpec(block: ContentBlock): MapSpecV1 | null { + if (!isRecord(block.payload)) return null; + const candidate = isRecord(block.payload.spec) ? block.payload.spec : block.payload; + if ( + !isString(candidate.title) + || candidate.title.trim().length === 0 + || candidate.title.length > MAX_LABEL_CHARS + || candidate.tile_source_id !== undefined + || !isRecord(candidate.feature_collection) + ) { + return null; + } + const collection = candidate.feature_collection; + if ( + collection.type !== "FeatureCollection" + || !Array.isArray(collection.features) + || collection.features.length > MAX_FEATURES + ) { + return null; + } + const features = collection.features.flatMap((feature) => { + if (!isRecord(feature) || feature.type !== "Feature" || !isRecord(feature.geometry)) return []; + const geometry = feature.geometry; + if ( + !isString(geometry.type) + || !["Point", "LineString", "Polygon"].includes(geometry.type) + || !areCoordinatesValid(geometry.coordinates) + ) { + return []; + } + if (feature.properties !== undefined && !isRecord(feature.properties)) return []; + const entries = feature.properties ? Object.entries(feature.properties) : []; + if ( + entries.length > MAX_PROPERTIES + || entries.some(([key, value]) => !isString(value) || key.length > MAX_LABEL_CHARS || value.length > MAX_LABEL_CHARS) + ) { + return []; + } + const properties: Record | undefined = entries.length > 0 + ? Object.fromEntries(entries) as Record + : undefined; + return [{ + type: "Feature" as const, + geometry: { type: geometry.type as GeoJsonFeature["geometry"]["type"], coordinates: geometry.coordinates }, + properties, + }]; + }); + if (features.length !== collection.features.length) return null; + + const rawMarkers = candidate.markers ?? []; + if (!Array.isArray(rawMarkers) || rawMarkers.length > MAX_FEATURES) return null; + const markers = rawMarkers.flatMap((marker) => { + if ( + !isRecord(marker) + || typeof marker.longitude !== "number" + || typeof marker.latitude !== "number" + || !isCoordinatePair([marker.longitude, marker.latitude]) + || !isString(marker.label) + || marker.label.length > MAX_LABEL_CHARS + ) { + return []; + } + return [{ longitude: marker.longitude, latitude: marker.latitude, label: marker.label }]; + }); + if (markers.length !== rawMarkers.length) return null; + + const initialView = candidate.initial_view === undefined ? undefined : readView(candidate.initial_view); + const bounds = candidate.bounds === undefined ? undefined : readBounds(candidate.bounds); + if ((candidate.initial_view !== undefined && !initialView) || (candidate.bounds !== undefined && !bounds)) return null; + + return { + title: candidate.title, + summary: isString(candidate.summary) && candidate.summary.length <= MAX_LABEL_CHARS ? candidate.summary : undefined, + feature_collection: { type: "FeatureCollection", features }, + markers, + attribution: isString(candidate.attribution) && candidate.attribution.length <= MAX_LABEL_CHARS ? candidate.attribution : undefined, + initial_view: initialView ?? undefined, + bounds: bounds ?? undefined, + }; +} diff --git a/src/lib/ipc/artifacts.ts b/src/lib/ipc/artifacts.ts index 45e2e58..9cd70da 100644 --- a/src/lib/ipc/artifacts.ts +++ b/src/lib/ipc/artifacts.ts @@ -22,6 +22,8 @@ export const artifactsIpc = { invoke("artifact_delete_or_expire", { sessionId, artifactId }), exportChartCsv: (sessionId: string, messageId: string, spec: unknown) => invoke("chart_export_csv", { sessionId, messageId, spec }), + exportMapGeojson: (sessionId: string, messageId: string, spec: unknown) => + invoke("map_export_geojson", { sessionId, messageId, spec }), appendBlock: (block: ContentBlock) => invoke("append_content_block", { block }), getMessageBlocks: (messageId: string) => diff --git a/src/locales/en/chat.json b/src/locales/en/chat.json index 03f5de3..4fa41d4 100644 --- a/src/locales/en/chat.json +++ b/src/locales/en/chat.json @@ -161,6 +161,7 @@ "map": { "copyCoordinates": "Copy GeoJSON", "toggleFeatures": "Show or hide map features", + "resetView": "Reset map view", "exportGeojson": "Export GeoJSON", "copyFailed": "Couldn't copy the GeoJSON.", "exportFailed": "Couldn't export the GeoJSON.", @@ -169,7 +170,8 @@ "fallbackFeatures": "Map unavailable; showing features instead.", "visualization": "Map visualization", "featureCount_one": "{{count}} feature", - "featureCount_other": "{{count}} features" + "featureCount_other": "{{count}} features", + "featureListTruncated": "Showing the first 200 of {{count}} features." } } } diff --git a/src/locales/zh-CN/chat.json b/src/locales/zh-CN/chat.json index a0af1c6..a1c7f8f 100644 --- a/src/locales/zh-CN/chat.json +++ b/src/locales/zh-CN/chat.json @@ -161,6 +161,7 @@ "map": { "copyCoordinates": "复制 GeoJSON", "toggleFeatures": "显示或隐藏地图要素", + "resetView": "重置地图视图", "exportGeojson": "导出 GeoJSON", "copyFailed": "无法复制 GeoJSON。", "exportFailed": "无法导出 GeoJSON。", @@ -169,7 +170,8 @@ "fallbackFeatures": "地图不可用,正在显示要素。", "visualization": "地图可视化", "featureCount_one": "{{count}} 个要素", - "featureCount_other": "{{count}} 个要素" + "featureCount_other": "{{count}} 个要素", + "featureListTruncated": "仅显示前 200 个要素,共 {{count}} 个。" } } } From 677504b4866d9ec1a6447767a7e943f2fd8441a2 Mon Sep 17 00:00:00 2001 From: knqiufan Date: Sun, 9 Aug 2026 09:31:42 +0800 Subject: [PATCH 16/16] docs(rich-content): hand off completed r0-r4 delivery --- .../00-overall-implementation-plan.md | 146 ++++++++++++ .../01-phased-module-practice-plan.md | 189 +++++++++++++++ .../02-architecture-design.md | 218 ++++++++++++++++++ .../03-functional-design.md | 149 ++++++++++++ .../rich-content-delivery/04-ui-ux-design.md | 134 +++++++++++ .../05-filesystem-and-sandbox-research.md | 131 +++++++++++ .../06-implementation-log.md | 10 +- .../07-ai-coding-execution-guide.md | 190 +++++++++++++++ .../08-research-sources.md | 60 +++++ .../rich-content-delivery/09-r0-r4-handoff.md | 86 +++++++ docs/planning/rich-content-delivery/README.md | 43 ++++ 11 files changed, 1351 insertions(+), 5 deletions(-) create mode 100644 docs/planning/rich-content-delivery/00-overall-implementation-plan.md create mode 100644 docs/planning/rich-content-delivery/01-phased-module-practice-plan.md create mode 100644 docs/planning/rich-content-delivery/02-architecture-design.md create mode 100644 docs/planning/rich-content-delivery/03-functional-design.md create mode 100644 docs/planning/rich-content-delivery/04-ui-ux-design.md create mode 100644 docs/planning/rich-content-delivery/05-filesystem-and-sandbox-research.md create mode 100644 docs/planning/rich-content-delivery/07-ai-coding-execution-guide.md create mode 100644 docs/planning/rich-content-delivery/08-research-sources.md create mode 100644 docs/planning/rich-content-delivery/09-r0-r4-handoff.md create mode 100644 docs/planning/rich-content-delivery/README.md diff --git a/docs/planning/rich-content-delivery/00-overall-implementation-plan.md b/docs/planning/rich-content-delivery/00-overall-implementation-plan.md new file mode 100644 index 0000000..da4879b --- /dev/null +++ b/docs/planning/rich-content-delivery/00-overall-implementation-plan.md @@ -0,0 +1,146 @@ +# 富内容与产物交付总体实施方案 + +> **用途:** 定义聊天富内容能力的目标架构、实施顺序、边界和验收标准。 +> **受众:** 产品、架构、全栈开发和安全维护者。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **状态:** R0–R4 已实现并通过远程 CI;R5、R6 仍作为后续计划。本文件保留总体基线与验收方向。 + +--- + +## 1. 目标与范围 + +用户与 Agent 对话时,助手回复除 Markdown 外还应能在聊天流内显示并操作: + +1. 统计图:柱状、折线、面积、散点、饼/环、条形、指标卡及可访问的数据表替代。 +2. 地图:首期显示结构化点、线、面、GeoJSON 和视口;后续支持受控瓦片与交互。 +3. 生成文件:在应用内预览支持的格式,并将原始文件保存到用户指定位置。 +4. 全模态模型图片:展示、放大和下载模型生成的图片。 +5. 保持已有 Markdown、代码、表格、Mermaid、数学公式、工具调用、流式显示、会话分页/导入导出行为不回退。 + +首期不做任意网页嵌入、任意 JavaScript 图表、远程 Office 在线查看器、云端文件托管或通用文件管理器。这些选项会扩大 WebView、网络和隐私攻击面,不能作为“在线查看”的默认实现。 + +## 2. 当前基线与主要缺口 + +| 层 | 已有能力 | 富内容缺口 | +|---|---|---| +| React | `Streamdown` 已渲染 Markdown、Mermaid、数学公式;`MessageItem` 已展示用户图片附件 | 助手消息只有 `content: string`;没有可插拔块渲染、产物工具栏、文件预览或图片输出状态 | +| 流式事件 | `stream_token`、`stream_thinking`、`stream_complete`、工具事件 | 只能推送文本增量;没有块完成、产物就绪、预览失败等事件 | +| Rust/SQLite | `messages` 保存正文、附件 JSON、思考和工具调用;自定义 `fs_*` command 已有工作区 root containment | 没有产物身份、内容哈希、生命周期、预览派生物、授权下载、保留策略和块顺序 | +| 模型链路 | Rig 具备图片输入;Sidecar 已预留流式协议 | 未把模型/工具的图表、地图、文件、图片标准化为可验证的输出契约 | +| 安全 | 主 WebView 已取消通用 FS/HTTP/Shell 权限,CSP 为本地严格策略 | 需要为受控本地产物增加窄 URI/asset 范围;不能重新打开宽权限 | + +以上判断来自当前 `src/lib/ipc/types.ts`、`use-stream-listener.ts`、`services/llm/backend.rs`、`MessageItem.tsx`、`fs_explorer.rs`、`tauri.conf.json` 的实际代码;详细证据见 [08-research-sources.md](./08-research-sources.md)。 + +## 3. 总体决策 + +### 3.1 用“内容块”替代 Markdown 指令和中间件链 + +采用版本化的 `ContentBlock` 判别联合,而不是让模型在 Markdown 中嵌入自定义 HTML、代码围栏约定或任意 JSON。每个 assistant 消息按顺序包含 `markdown`、`chart`、`map`、`artifact`、`image`、`notice` 等块;未知版本或未知类型必须安全降级为提示卡和原始元数据下载,不执行内容。 + +前端采用 **Renderer Registry(注册表)** 按块类型寻找渲染器;每个渲染器只接收已验证 DTO。相比 middleware,中间件更适合处理请求/响应横切流程,不能自然表达“消息中第 N 个独立可持久化对象”的生命周期、重试、无障碍替代和懒加载。 + +### 3.2 用受控 ArtifactService 管理所有二进制与文件 + +图像、生成文件、预览缩略图、PDF 页面位图等不进入 `messages.content`,也不把完整 Base64 长期塞进消息 JSON。Rust 侧的 `ArtifactService` 负责:接收、配额与 MIME 侦测、内容哈希、原子落盘、预览任务、读取授权、导出保存、清理和审计。消息只持久化 `artifact_id` 和不可变摘要。 + +### 3.3 首期选择“安全数据渲染”,不执行模型生成代码 + +- 图表接收受限的、无函数的规范化数据/编码,而不是原生 ECharts `Option` 或 HTML/JavaScript。 +- 地图首期接收 GeoJSON/marker 的数据子集;瓦片来源只能引用管理员/用户已配置的 `tile_source_id`,不能由模型给出任意 URL。 +- 文件预览按 MIME Strategy 选择本地解析器;不调用在线 Office Viewer,也不把用户文件上传到第三方。 +- 图片仅放行 raster MIME(PNG/JPEG/WebP/GIF);SVG/HTML 等活跃内容默认作为下载文件,不内联到主聊天 WebView。 + +### 3.4 把“显示安全”与“执行 Sandbox”分层 + +受控文件存储、WebView URI 范围、CSP、内容 schema 和解析资源限制是本功能必需的 **内容安全面**。完整 OS Sandbox 是执行面:当 Agent、Skill 或 MCP 运行外部命令、复杂转换器或不可信二进制时,后续必须接入现有 `SandboxBroker`。二者不能互相替代。 + +## 4. 目标架构 + +```mermaid +flowchart LR + MODEL["LLM / Agent / MCP tool"] --> NORMALIZE["Output adapter + schema validation"] + NORMALIZE --> BLOCKS["MessageBlockService"] + NORMALIZE --> ARTIFACTS["ArtifactService"] + ARTIFACTS --> STORE["App-owned artifact store\nhash + quota + lifecycle"] + BLOCKS --> DB[("SQLite\nmessages + message_blocks + artifacts")] + ARTIFACTS --> DB + BLOCKS --> EVENTS["Tauri domain events"] + EVENTS --> CHAT["React message store"] + DB --> CHAT + CHAT --> REGISTRY["Renderer Registry"] + REGISTRY --> MD["Markdown renderer"] + REGISTRY --> CHART["Chart renderer"] + REGISTRY --> MAP["Map renderer"] + REGISTRY --> PREVIEW["Artifact preview strategy"] + REGISTRY --> IMAGE["Image viewer"] + PREVIEW --> URI["Scoped artifact URI / read command"] + IMAGE --> URI + ARTIFACTS --> EXPORT["Dialog save + Rust copy"] + AGENTEXEC["Agent / Skill external execution"] -. "future, brokered" .-> SANDBOX["SandboxBroker + network policy"] +``` + +## 5. 推荐实施顺序 + +| 阶段 | 可见交付 | 关键依赖 | 是否阻塞完整 Sandbox | +|---|---|---|---| +| R0 | 统一 DTO、Schema、迁移、feature flag、安全测试基线 | 现有聊天回归测试 | 否 | +| R1 | 文件/图片产物的可靠保存、展示元数据、下载 | ArtifactService、窄 IPC/URI | 否 | +| R2 | PDF、文本、表格等本地预览与失败回退 | 解析器 Strategy、资源限制 | 否;高风险转换器后接 Sandbox | +| R3 | 受限图表块、数据表替代、导出 | Renderer Registry、ECharts adapter | 否 | +| R4 | 静态 GeoJSON 地图;受控瓦片试点 | Map renderer、地图数据策略 | 否;远程瓦片需网络/CSP policy | +| R5 | Sidecar/Agent/MCP 规范化产出、权限与审计 | Phase 4 对话迁移、MCP loop | 部分依赖现有 Sandbox 计划 | +| R6 | 安全加固、跨平台验证、清理和发布 | R0–R5、Sandbox 平台能力 | 是,涉及外部执行时 | + +详细工作包与退出条件在 [01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md)。 + +## 6. 文件系统与 Sandbox 结论 + +### 6.1 是否需要文件系统能力 + +需要,但必须限定为 **Rust Core 的应用专属产物目录** 与 **用户显式选择的导出路径**: + +- Rust 可使用 `std::fs`/`tokio::fs`,并通过自定义 command 验证 `artifact_id`、会话归属、大小、哈希、允许 MIME 和保存目标。 +- React 不安装 `@tauri-apps/plugin-fs`,不获得 `$HOME`、工作区或任意路径 read/write scope。 +- WebView 展示通过 scoped `asset:` 或自定义 `misakax-artifact:` URI;路径不能来自模型或前端字符串。 +- 工作区中由 Agent 创建的文件先快照/复制入产物目录,再作为 Artifact 引用;不得向 WebView 暴露工作区原始路径。 + +### 6.2 是否需要 Sandbox + +不需要把完整 OS Sandbox 作为上述静态展示的上线门槛;它不能解决 HTML/XSS、错误 MIME、解压炸弹或 WebView 权限问题。需要在计划中新增以下衔接: + +- R0 建立 `ContentSafetyPolicy`,包含文件大小、类型、解析时间/页数、像素、嵌套压缩和 URI 授权。 +- R2 对 CPU/内存密集或原生二进制转换器采用独立受限 worker;在 Sandbox Provider 可用前,不可用时应拒绝预览并保留下载。 +- R5/R6 将 Agent/Skill/MCP 的外部生成过程接入 `SandboxBroker`;网络地图瓦片走受控 provider/broker,不让 WebView 任意直连。 + +完整矩阵与理由见 [05-filesystem-and-sandbox-research.md](./05-filesystem-and-sandbox-research.md)。 + +## 7. 成功标准 + +1. 旧消息和纯 Markdown 消息渲染无变化,新块在流式与历史加载中顺序稳定。 +2. 所有可下载产物有 ID、原文件名、MIME、字节数、SHA-256、创建来源和保留状态;导出后校验哈希一致。 +3. 主 WebView 不拥有通用文件系统、HTTP 或 Shell 权限;错误 ID、路径猜测和任意 `file:` URL 均不能读取产物。 +4. 图表和地图只渲染结构化数据;模型输出的脚本、远程 iframe、任意 tile URL 和内联 SVG 不能执行。 +5. 每个图表提供可访问摘要和表格数据;地图提供要素列表/坐标文本;所有操作可键盘触达。 +6. 大文件、未知 MIME、损坏文件、解析超时、磁盘不足、过期引用均以可理解的本地化错误降级,不导致会话丢失或崩溃。 +7. Agent/MCP 产物的来源、用户导出和策略拒绝均进入结构化审计;涉及外部程序时符合既有 Sandbox 策略。 + +## 8. 风险与非目标 + +| 风险 | 策略 | +|---|---| +| 模型返回伪造/恶意结构 | 只接收工具/adapter 产出的 schema;Rust 再验证;未知块 fail closed | +| Base64/大 JSON 使 SQLite、导出和滚动变慢 | 二进制离库;块/预览懒加载;内容哈希去重与配额 | +| 文件解析器遭遇畸形文件或资源耗尽 | 类型 allowlist、魔数检测、页/行/像素/时间上限;必要时 worker + Sandbox | +| 地图瓦片带来隐私、密钥和 CSP 扩张 | 静态 GeoJSON 优先;受控 tile source、Rust broker、缓存和 attribution | +| 组件注册表沦为散乱 if/else | 明确渲染器端口、能力声明、契约测试与 feature flag | +| 直接修改既有 `content` 造成历史损坏 | 新表/dual-read/dual-write,迁移完成后再切换读路径 | + +## 9. 决策门 + +开始 R1 前必须确认:受控 URI 选择(窄 `asset:` scope 或自定义协议)和产物存储保留策略。 + +开始 R2 前必须确认:首期预览 MIME allowlist、单文件/会话/总量配额及 PDF/Office 解析方案许可证。 + +开始 R4 前必须确认:是否有合法的地图数据/瓦片服务、隐私提示、attribution、缓存上限和在线/离线行为。 + +开始 R5 前必须确认:Sidecar 已从 501 占位迁移至真实对话链路;外部执行是否已满足 Sandbox Provider 的对应平台 gate。 diff --git a/docs/planning/rich-content-delivery/01-phased-module-practice-plan.md b/docs/planning/rich-content-delivery/01-phased-module-practice-plan.md new file mode 100644 index 0000000..dd33993 --- /dev/null +++ b/docs/planning/rich-content-delivery/01-phased-module-practice-plan.md @@ -0,0 +1,189 @@ +# 富内容与产物交付:分模块分阶段实践方案 + +> **用途:** 将总体方案拆为可独立验收、可回滚的实施工作包。 +> **受众:** 实施开发者、测试和 AI Coding Agent。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **状态:** R0–R4 已按阶段门禁完成;R5、R6 保持后续规划。实现和 CI 证据见 [实施过程记录](./06-implementation-log.md) 与 [R0–R4 交接](./09-r0-r4-handoff.md)。 + +--- + +## 0. 全局实施规则 + +- 每一阶段先补特征/契约测试,再添加 DTO、迁移和调用点;不要先大规模移动现有聊天文件。 +- 任何数据库迁移必须向前兼容:旧 `messages.content` 仍可读,导入/导出在过渡期不得静默丢失块或附件。 +- `artifact_id` 是唯一跨层引用;前端、模型、工具和 URI 不传宿主绝对路径。 +- 所有二进制、解析、下载、预览均通过 Rust application service;React 只请求 metadata、一次性预览 URL 或显式 download/export command。 +- 每一个新事件携带 `message_id`、`block_id`、`generation`/`revision`;前端丢弃已重生成、已删除或不属于当前会话的迟到事件。 +- 每个阶段完成后先通过代码审查和全部相关本地测试,再更新 [实施过程记录](./06-implementation-log.md)、提交并非强制推送当前阶段;只有远程仓库 required CI 全绿且所需 reviewer 已批准,才能启动下一阶段。完整门禁见 [AI Coding 执行说明 §7](./07-ai-coding-execution-guide.md#7-阶段完成门禁代码审查本地验证git-与远程-ci)。 +- 涉及 UI 时同步项目 `docs/design/` 规范;远程 CI 失败或不可查询时,当前阶段保持未完成,按执行说明处理。 + +## R0:契约、安全基线与可迁移数据模型 + +### 目标 + +在不改变现有用户界面的前提下,定义统一内容块和产物领域模型,为后续模块提供稳定边界。 + +### 工作包 + +1. 在 Rust 领域层定义 `ContentBlock`、`ArtifactRecord`、`ArtifactOrigin`、`PreviewStatus`、`ContentSafetyPolicy` 和稳定错误码。 +2. 在 `src/lib/ipc/` 定义同构 TypeScript DTO;用判别联合和 exhaustive switch,禁止以 `any`/字符串约定解析块。 +3. 新增数据库迁移:`message_blocks`(message、顺序、类型、schema version、payload JSON、状态)和 `artifacts`(身份、元数据、哈希、存储 key、来源、保留信息),并为 message/artifact 建索引。 +4. 在导入/导出模型加入 `blocks` 和 `artifact_manifest`,旧数据仍从 `content` 和 `attachments` 恢复为兼容块。 +5. 新增 feature flag:默认关闭新块写入/渲染;实现 dual-read,暂不删除旧字段。 +6. 建立安全测试样本:路径穿越、错误 MIME、伪造扩展名、超限 payload、未知块类型、过期/越权 artifact ID。 + +### 建议代码落点 + +| 层 | 建议新增/调整位置 | +|---|---| +| Rust domain/application | `src-tauri/src/services/content/`、`services/artifacts/`,后续稳定后再按现有架构计划移动 | +| DB | `src-tauri/src/db/migrations.rs`、`db/models.rs`、`db/repository/message_repo.rs`,新增 block/artifact repository | +| IPC | `src/lib/ipc/types.ts`、新增 `src/lib/ipc/artifacts.ts`;保持 `chat.ts` 兼容包装 | +| 测试 | `src/__tests__/rich-content-*`、`src-tauri/tests/rich_content_*` | + +### 验收与回滚 + +- 旧会话、搜索、重新生成、导入/导出、纯 Markdown 流式测试全绿。 +- 插入未知块不崩溃,展示受控“暂不支持”状态;任何非法 artifact ID 被拒绝。 +- feature flag 关闭时只走旧消息读写路径;迁移可保留数据且无二进制 blob 写入 `messages.content`。 + +## R1:ArtifactService、图片输出与可靠下载 + +### 目标 + +先形成最小闭环:Agent/工具可产生受控图片或文件,消息显示产物卡,用户可保存下载。 + +### 工作包 + +1. 实现应用专属 artifact store:临时文件写入、magic bytes/MIME 检查、SHA-256、原子 rename、大小/总量配额、引用计数或保留时间。 +2. 实现 `artifact_register`、`artifact_get_metadata`、`artifact_export`、`artifact_delete_or_expire` application use case;导出只能通过 `dialog:allow-save` 选择目标后由 Rust copy,不能让 WebView 写路径。 +3. 选择窄资源通道:优先评估仅暴露 artifact root 的 `asset:` scope;如需按 session/revision 鉴权或 range 请求,改为异步 `misakax-artifact:` URI protocol。无论哪种方案都不得接受任意绝对路径。 +4. 增加 `image` 与通用 `artifact` 块;助手图片支持 PNG/JPEG/WebP/GIF 的缩略图、原始尺寸查看、另存为和错误占位。 +5. 图片由 provider adapter 或受控工具注册后再写块;不把模型返回的 URL 直接赋给 ``,也不内联 SVG。 +6. 实现清理/磁盘满/哈希不匹配/文件缺失的稳定错误反馈和审计事件。 + +### 测试重点 + +- 导出的字节数/哈希与库存档一致;取消保存不产生垃圾文件。 +- SVG、HTML、伪造 `image/png`、超像素/超大图片不能进入主聊天预览。 +- 一条会话不能读取另一条会话的未公开预览 URI;已删除/过期 ID 不可复用。 +- 现有用户图片输入附件仍可显示、可随历史重放给模型。 + +## R2:文件预览模块 + +### 目标 + +支持常见生成文件的就地查看与下载,并且“无法安全预览”始终可退化为下载。 + +### 首期 MIME allowlist + +| 格式 | 展示方式 | 说明 | +|---|---|---| +| `text/plain`、Markdown、JSON、CSV | 虚拟化文本/表格预览 | 限制行数、单行长度、总字符数;支持原始下载 | +| PDF | 本地 PDF.js viewer/受控页面 | 限制页数、文件大小与渲染并发;不使用 `file:` | +| XLSX | 本地二进制解析为受限表格 | 首期只读、sheet 切换和表格虚拟化;公式不执行 | +| DOCX | 本地转换为安全文档片段或仅文本预览 | 不加载远程资源、宏或嵌入对象;效果不等同 Word | +| 其他/压缩包/可执行文件 | metadata + 下载 | 默认不预览 | + +### 工作包 + +1. 定义 `Previewer` Strategy:`canPreview(metadata)`、`prepare(artifact)`、`getViewModel()`、`dispose()`;注册表按 MIME + magic bytes 选择,而非后缀。 +2. 预览任务与主聊天列表分离:点击后懒加载,显示可取消进度;取消/离开会话时中止并释放对象 URL/worker。 +3. 对 CSV/XLSX/DOCX/PDF 应用页数、行列、解压、时间、内存与并发限制;输出只保留受限 preview derivative,不保存任意解析脚本。 +4. R2 初期禁用 HTML、SVG、Office 宏、嵌入对象、任意 iframe 和远端图片;若未来支持,必须先完成独立 renderer sandbox 设计评审。 +5. 预览面板可在聊天卡内展开,也可使用受限的二级 `Dialog`;不新建拥有主窗口 capability 的通用远程 webview。 + +### 退出门 + +- 受支持格式可预览,任意失败均可下载原件。 +- 损坏、加密、超限、压缩炸弹、超时文件不使主进程/聊天列表崩溃。 +- UI 清楚区分“预览副本”“原文件”“仅下载”;不承诺编辑或完全保真。 + +## R3:统计图模块 + +### 目标 + +以结构化数据渲染可靠、可访问的统计图,并与 Markdown 表格互补。 + +### 工作包 + +1. 定义 `ChartSpec v1`,只包含图表类型、标题/说明、维度、数值数据、编码、排序、单位、色板语义和可选注释;禁止函数、任意 HTML formatter、任意外部资源 URL。 +2. 新增 `chart` 块的 schema validator 与 `ChartRenderer`;渲染器把 `ChartSpec` 编译为 ECharts option,而不是把 provider 原样 option 透传。 +3. 首期实现 line/bar/area/scatter/pie/metric 六类,控制 series/point/label 上限,超限自动转为聚合/表格提示。 +4. 必须加载 ECharts ARIA 组件,给每张图提供简短文本摘要、隐藏/展开的数据表、键盘可达的导出和重置视图。 +5. 图片导出在客户端从已验证 SVG/canvas 生成;数据导出走 ArtifactService 创建 CSV,而非直接拼页面 DOM。 +6. 通过“生成图表”工具/adapter 写入 spec;模型无法直接在 Markdown 中构造带脚本的图。 + +### 验收 + +- 同一 spec 在重新打开、导入会话、深浅主题和窗口大小变化后语义一致。 +- 色盲、屏幕阅读器、键盘用户可得到与视觉图等价的关键数据。 +- 过大/非法 spec 或图表库加载失败时降级到数据表/notice,不影响整条消息。 + +## R4:地图模块 + +### 目标 + +先实现不扩张网络权限的地图数据展示,再谨慎加入受控在线瓦片。 + +### 工作包 + +1. 定义 `MapSpec v1`:GeoJSON FeatureCollection、marker、bounds、初始视角、只读 label/属性和 attribution;禁止 JS 表达式、任意 HTML popup、`file:` 与模型给出的 tile URL。 +2. 实现 `MapRenderer`,动态加载 MapLibre GL JS,并以 WebGL unavailable/地图数据错误/超要素数为可恢复状态。 +3. R4a 仅使用本地 GeoJSON + 明确的基础底图策略;保存地图的静态视图/数据导出通过 ArtifactService。 +4. R4b 如产品确认在线瓦片,创建 `TileSourceRegistry`(ID、许可、attribution、允许域、密钥来源、缓存与离线策略),请求经 Rust broker/custom URI 代理;不把宽 `https:` 加入主 WebView CSP。 +5. 补充坐标文本、要素列表和“复制坐标/导出 GeoJSON”替代交互;定位用户当前位置必须单独征得用户权限,不由模型触发。 + +### 验收 + +- 地图数据没有网络时仍能给出正确要素信息或降级提示。 +- 未登记瓦片源、任意 URL、过大 GeoJSON、跨会话 URI 都被拒绝。 +- 每张地图都有 attribution、文本等价信息和键盘控制说明。 + +## R5:Agent、Sidecar、MCP 和执行安全整合 + +### 目标 + +让所有生成路径以同一规范写入块/产物,不让 provider 差异泄漏进前端。 + +### 工作包 + +1. 在 Rust provider 和 Python Sidecar 建立 `RichOutputAdapter`:将多家模型的文本、图像、工具结果转换为 canonical blocks;所有产物先注册后引用。 +2. 为 Agent 提供窄工具:`present_chart`、`present_map`、`create_artifact`、`attach_image`;工具入参是 schema,不能接收 URI、宿主路径、HTML 或代码。 +3. 扩展 SSE/Tauri 事件为 block lifecycle:`stream:block_started`、`stream:block_ready`、`stream:block_failed`;保留现有 token/thinking/complete 事件兼容。 +4. MCP 工具结果先经过 Artifact ingress policy、来源标记和用户权限;未经批准的 MCP 不能直接注册可展示资源。 +5. 对需要运行转换器/生成器的 Agent、Skill、MCP 路径接入 `SandboxBroker` 的 `workspace-write`/`read-only` policy;未完成的 OS provider 不得自动退回宿主执行。 + +### 退出门 + +- Rig fallback 与 Sidecar 主链均能生成同一种 canonical block。 +- 取消、重生成、MCP 拒绝、Sidecar 重启和流结束异常不会留下孤立 artifact 或错配 block。 +- 每个产物可追踪来源(模型/Agent/Skill/MCP/用户)、会话和触发消息。 + +## R6:性能、安全加固与发布 + +### 工作包 + +1. 做大小、内存、GPU、地图 tile、PDF 页、XLSX 解压与消息虚拟列表基准;为超限确立产品可见阈值。 +2. 三平台验证 custom/asset URI、文件名 Unicode、长路径、保存对话框、WebView2/WebKitGTK、GPU/WebGL 退化和清理任务。 +3. 完成安全回归:XSS、恶意 SVG/HTML、路径 traversal/symlink、MIME confusion、zip bomb、URI auth、CSP/capability diff、超时/取消和跨会话访问。 +4. 对需要外部执行的 preview/generator,按既有 Sandbox B0–B7 平台 gate 验证;无 strict provider 时明确禁用该可执行路径。 +5. 完成保留策略、手动“清理产物”、隐私/地图 attribution 文案、可观测性和 release notes。 + +## 依赖与并行性 + +```mermaid +flowchart LR + R0 --> R1 + R0 --> R3 + R0 --> R4 + R1 --> R2 + R1 --> R5 + R2 --> R6 + R3 --> R6 + R4 --> R6 + R5 --> R6 + SB["Existing Sandbox B0–B5"] -. "external converters / agent execution" .-> R5 +``` + +R3 和 R4 可以在 R0 完成后并行;R2 必须复用 R1 的存储和授权;R5 的非执行部分可先做 adapter/事件,涉及外部进程的部分等待对应 Sandbox gate。 diff --git a/docs/planning/rich-content-delivery/02-architecture-design.md b/docs/planning/rich-content-delivery/02-architecture-design.md new file mode 100644 index 0000000..9ffb076 --- /dev/null +++ b/docs/planning/rich-content-delivery/02-architecture-design.md @@ -0,0 +1,218 @@ +# 富内容与产物交付架构设计 + +> **用途:** 规定领域模型、模块边界、协议、持久化与安全边界,供代码实现和架构评审使用。 +> **受众:** React、Rust、Python Sidecar、MCP 与安全维护者。 +> **最后审阅 / Last reviewed:** 2026-08-08 +> **状态:** Proposed。 + +--- + +## 1. 架构原则 + +1. **数据优先,不执行内容。** 模型生成的图表/地图/文件描述均是数据;主 WebView 不执行模型提供的 JavaScript、HTML、CSS、URL handler 或 shell 命令。 +2. **产物离开消息正文。** SQLite 消息持久化引用和小型结构化 payload;字节存放在应用拥有的文件树,使用哈希、配额和原子写入保证一致性。 +3. **端口-适配器。** 核心领域不依赖 React、Tauri URI、ECharts、MapLibre、PDF.js、LangChain 或特定 provider;这些实现都在 adapter 层。 +4. **单一权威。** Rust 是 artifact 身份、授权、MIME、存储、预览状态、保留策略与审计的唯一所有者。React 是投影,Sidecar 是请求方,不维护第二套状态。 +5. **向前兼容。** 块包含 `schema_version`;未知类型不执行、可诊断、可下载原 payload。旧消息仍能由 `content` 合成为单一 Markdown 块。 +6. **最小暴露。** 主 WebView 无通用 FS/HTTP/Shell;可显示字节只能来自受控 artifact URI 或明确的 IPC 读取结果。 + +## 2. 领域模型与消息契约 + +### 2.1 Canonical ContentBlock + +概念模型如下,实际字段名沿用仓库 Rust/TypeScript snake_case 约定并在实现时保持两端一致: + +```ts +type ContentBlock = { + id: string; // UUID;消息内稳定身份 + schemaVersion: 1; + kind: "markdown" | "chart" | "map" | "artifact" | "image" | "notice"; + status: "pending" | "ready" | "failed" | "unsupported"; + payload: unknown; // 按 kind 由 Rust schema 验证后的 JSON + fallback: BlockFallback; // 无法渲染时的安全文本/下载指引 +}; + +type BlockFallback = { + title: string; + messageKey: string; + params?: Record; + artifactId?: string; +}; +``` + +块在同一消息中通过单调 `position` 排序,不能依赖消息渲染时的数组 append 顺序。`status` 是显示状态,不代表文件可访问性;可访问性仍由 artifact/session/revision 授权决定。 + +### 2.2 类型 payload + +| kind | 最小 payload | 禁止项 | +|---|---|---| +| `markdown` | `text` | 内嵌新富内容协议、信任 HTML | +| `chart` | `ChartSpecV1`、文本摘要、可选数据 artifact ID | JS function、HTML formatter、外部脚本/URL | +| `map` | `MapSpecV1`、attribution、GeoJSON/data artifact ID | 任意 tile URL、HTML popup、位置权限触发 | +| `artifact` | `artifact_id`、展示名、preview hint | 宿主路径、预先签名的外部 URL | +| `image` | `artifact_id`、width/height/alt source | SVG/HTML 直显、base64 长期重复存储 | +| `notice` | i18n message key/params、severity | 后端自然语言错误解析 | + +`ChartSpecV1` 与 `MapSpecV1` 是本项目规范,而不是第三方库的原始配置。编译器把受限 spec 映射到 ECharts/MapLibre;第三方库升级时不改变消息历史语义。 + +### 2.3 ArtifactRecord + +```text +ArtifactRecord + artifact_id UUID + owner_session_id 会话授权边界 + origin_message_id 创建消息(可为空,供用户导入) + origin_kind model | agent | mcp | skill | user | preview + display_name 安全化后的显示名 + media_type magic bytes + allowlist 结果 + byte_size / sha256 完整性和审计 + storage_key 仅 Rust 解释,不是路径 + preview_state none | queued | ready | failed | unsupported + preview_artifact_id 派生预览;可为空 + retention_state active | expired | deleted + created_at / expires_at +``` + +数据库建议将 `message_blocks` 和 `artifacts` 分表。小型 block payload 允许 JSON 文本存储;二进制一律不入 SQLite。为 `message_id + position`、`session_id + retention_state`、`sha256`、`origin_message_id` 加索引。专用 `artifact_references` 表在一个产物可被多个消息或导出记录引用时再引入,避免初期过度建模。 + +## 3. 模块与依赖方向 + +```text +src-tauri/src/ + services/ + content/ + types.rs # ContentBlock、ChartSpec、MapSpec、validator port + block_service.rs # append/finalize/read block application use cases + normalizer.rs # provider/tool output -> canonical block adapter + artifacts/ + types.rs # ArtifactRecord、policy、error + ingress.rs # byte stream -> magic/MIME/hash/quota/atomic storage + repository.rs # metadata persistence port + export.rs # dialog target + verified copy + preview.rs # Previewer Strategy orchestration + uri.rs # asset/custom URI authorization adapter + cleanup.rs # retention and orphan cleanup + commands/ + artifacts.rs # thin DTO adapters only + db/repository/ + artifact_repo.rs + message_block_repo.rs + +src/ + features/chat-content/ + types.ts # canonical frontend DTO + renderer-registry.ts # kind -> renderer registration + MessageContentBlocks.tsx # ordered dispatcher, ErrorBoundary per block + renderers/{markdown,chart,map,artifact,image,notice}/ + hooks/{useArtifactPreview,useArtifactExport}.ts + lib/ipc/artifacts.ts + +agent/app/ + rich_output/ + schemas.py # provider-neutral Pydantic models + tools.py # narrow present_* / create_artifact tools + adapter.py # Sidecar event -> canonical output request +``` + +React 只能依赖 `lib/ipc` 和经过懒加载的 renderer adapter;`chart`、`map`、PDF/Office parser 不得进入 Chat 首屏包。Rust 的 command 只反序列化 DTO、验证 caller/session 后调用 application service;不得把安全判断散在 command 或前端。 + +## 4. 设计模式与适用位置 + +| 模式 | 用途 | 必须避免 | +|---|---|---| +| Registry | `BlockRendererRegistry`、`PreviewerRegistry`、provider normalizer 选择 | 巨型 `switch` 跨文件复制;运行时加载不受信任插件 | +| Strategy | MIME 预览、导出格式、地图 tile provider、保留策略 | 以文件扩展名作为唯一策略依据 | +| Adapter | OpenAI/Anthropic/Gemini/Rig/Sidecar/MCP 输出转 canonical blocks | 让前端知道每家 provider 的字段 | +| Facade/Application Service | `ArtifactService` 对存储、哈希、下载、审计暴露窄操作 | React 直接读写 artifact tree | +| State machine | block 和 preview lifecycle、流式完成、取消、清理 | 用布尔值组合表达互斥状态 | +| Policy object | `ContentSafetyPolicy`、URI authorization、tile source policy | 由模型/前端传平台参数、路径或 CSP 规则 | +| Observer/Event envelope | 流式块状态向 React 投影 | 只靠组件卸载取消后端任务 | + +“中间件”只用于可观测性、脱敏、审计等请求横切关注点;不承担决定“一个消息块该如何渲染”的职责。 + +## 5. 数据与流式时序 + +### 5.1 生成并展示一个产物 + +```mermaid +sequenceDiagram + participant A as Agent/Provider/MCP + participant N as Output normalizer + participant S as ArtifactService + participant D as SQLite + participant E as Tauri events + participant R as React Renderer + + A->>N: text delta or structured tool result + N->>S: register bytes/spec with origin context + S->>S: validate, hash, quota, atomic write + S->>D: persist ArtifactRecord + N->>D: persist pending/ready ContentBlock + N->>E: stream:block_ready(message, block, revision) + E->>R: update current message projection + R->>S: metadata/authorized preview request + S-->>R: scoped URI or safe ViewModel +``` + +文本仍沿用 `stream_token`。富内容绝不混入文本 token;流末 `stream_complete` 要带最终 block revision 或由前端以 `get_message_blocks` 回读权威记录,避免事件丢失导致历史不一致。 + +### 5.2 取消、重生成和失败 + +- `pending` block 只能由拥有同一 stream generation 的 ready/failed 事件推进。 +- 停止生成:取消未提交的临时文件;已原子提交但未被消息引用的产物标记 orphan,异步清理。 +- 重新生成:新 assistant message 获得新 block/artifact 归属;旧消息可继续查看,禁止就地覆盖历史产物。 +- preview 失败:保持原 artifact 可下载,写入 `preview_state=failed` 和稳定错误码,不把错误字符串覆盖原消息正文。 + +## 6. 存储、URI 与导出边界 + +### 6.1 存储布局 + +逻辑 key 可按内容哈希和 artifact ID 分层,例如 `objects/sha256/ab/cd/` 与 `metadata` 分离;不要从未净化的文件名拼目录。写入流程为“临时目录 → 流式限制/MIME 检查/哈希 → 原子 rename → SQLite 事务关联”;失败时回收临时文件。 + +应用目录应位于 MisakaX data root 下的单独 `artifacts/` 子目录,并从工作区、Skills、配置、日志和 WebView data 目录中隔离。数据库备份/会话导出应明确是否仅导出 manifest、连同内容导出还是提示用户另行打包。 + +### 6.2 资源传递方案 + +实现 Spike 要在两种窄方案中选一,记录测试证据: + +1. **Scoped `asset:` protocol:** 仅允许应用 artifact subtree,配置显式 allow/deny;适合可公开读取的本地预览。Tauri 的 asset scope 必须精确匹配静态路径,不能扩为 `$HOME/**/*`。 +2. **自定义 `misakax-artifact:` protocol:** URI 仅含 opaque artifact ID + revision,由 Rust 校验 WebView/session/状态并返回正确 MIME 与 range 响应;适合细粒度授权和缓存控制。 + +不论采用哪种,都不可将 `convertFileSrc` 的输入暴露给模型/React。图片、PDF viewer 和下载一律走该通道;禁止 `file:`、裸绝对路径及“临时把整个工作区加到 scope”。 + +### 6.3 导出 + +`artifact_export(artifact_id)` 获取用户保存目标后,由 Rust 以 no-follow/规范化目标策略复制并重算/校验 hash。名称用平台安全的文件名,冲突采用用户确认或可预测的“(n)”后缀;不覆盖既有用户文件。导出是副本,不改变 artifact 的引用或保留状态。 + +## 7. 内容安全策略 + +`ContentSafetyPolicy` 是独立于 OS Sandbox 的第一道策略,至少配置: + +| 分类 | 必需限制 | +|---|---| +| 输入与存储 | 单文件、单消息、会话、应用总大小;文件数;流中 chunk;写入时间 | +| 类型 | magic bytes 与 declared MIME 一致;allowlist;危险/未知类型仅下载 | +| 图像 | 像素数、宽高、动画帧/时间、解码内存;SVG 不直显 | +| 文档 | PDF 页数、XLSX 解压大小/工作表/单元格、DOCX 关系与嵌入对象、文本行列上限 | +| 图表/地图 | schema 深度、series/points/features、字符串长度、坐标范围、禁止可执行回调 | +| URI | ID/revision 归属、TTL、session/window scope、MIME 响应头、无路径泄露 | +| 运行 | 解析并发、超时、取消、worker 资源与审计;不可保证时仅下载 | + +对原生转换器、外部命令和不可信 helper,`ContentSafetyPolicy` 的拒绝不能以普通 `subprocess`/shell 回退;必须转交既有 `SandboxBroker` 或禁用该预览器。 + +## 8. 兼容与迁移 + +1. 新 schema 先 dual-write:assistant 文本继续写 `messages.content`,同时可写一个 `markdown` block。 +2. 读取顺序:有 `message_blocks` 则按块渲染;无则由 legacy adapter 构造 markdown/现有图片附件兼容视图。 +3. 导出加入新字段但仍保留旧 content;导入优先接受已验证 blocks,否则走 legacy parser。 +4. 历史图片附件不移动二进制数据的情况下保持显示;在用户主动打开/导出或后台可控迁移时才复制入 artifact store,避免一次升级大量 I/O。 +5. 新 renderer、previewer、map tiles、Sidecar rich tool 分别 feature flag;关闭后显示 fallback,而不是删除数据。 + +## 9. 架构验收清单 + +- [ ] Rust、TypeScript、Python 的 schema fixtures 双向一致,未知字段/版本策略明确。 +- [ ] 无块消息、旧附件、流式文本、工具调用、搜索、分页、导入导出回归通过。 +- [ ] 二进制不写入 `messages.content`,且没有前端任意路径读取入口。 +- [ ] 渲染器、预览器、provider adapter 可独立注册/测试,未触发包级循环依赖。 +- [ ] `ContentSafetyPolicy`、URI、MIME、配额和清理逻辑在 Rust 单一位置可审计。 +- [ ] 所有外部执行路径要么走 SandboxBroker,要么在 strict 模式下明确不可用。 diff --git a/docs/planning/rich-content-delivery/03-functional-design.md b/docs/planning/rich-content-delivery/03-functional-design.md new file mode 100644 index 0000000..41065a0 --- /dev/null +++ b/docs/planning/rich-content-delivery/03-functional-design.md @@ -0,0 +1,149 @@ +# 富内容与产物交付功能设计 + +> **用途:** 描述面向用户的功能、状态、异常和验收行为,不规定具体组件实现。 +> **受众:** 产品、前端、后端、测试和本地化维护者。 +> **最后审阅 / Last reviewed:** 2026-08-08 +> **状态:** Proposed。 + +--- + +## 1. 基本体验 + +助手消息是一条有序的内容流。Markdown 与富内容块交错出现;用户无需学习标记语法,也不需要打开外部网页即可查看支持格式。每个富内容块都有独立加载、失败和操作状态,任一块失败不能遮挡同一消息的其他正文或工具结果。 + +所有“下载”均表示用户选择本地保存位置后的文件副本;不上传到云端,也不把本地绝对路径发送给模型。所有“在线查看”在本方案中指 **应用内 WebView 预览**,并非第三方在线 Office 服务。 + +## 2. 图表 + +### 2.1 用户流程 + +1. Agent 需要以图表表达数据时,通过受控 `present_chart` 产出结构化 spec。 +2. 消息内显示图表标题、简短结论、图面与图例;加载中先保留固定高度 skeleton。 +3. 用户可查看“数据表”、复制关键结论、导出数据 CSV、导出图像、重置缩放/选择;无数据表则不显示导出数据动作。 +4. 数据不合法、过多或 renderer 失败时,显示简洁的“图表不可显示”卡和数据/说明 fallback;不得在正文输出原始脚本。 + +### 2.2 首期能力与限制 + +| 能力 | 支持 | 限制 | +|---|---|---| +| 图类型 | 折线、柱状、面积、条形、散点、饼/环、指标 | 仅 schema 中明示的类型 | +| 交互 | tooltip、legend、缩放、选择、重置 | 禁止自定义 JS/HTML formatter | +| 数据 | 内嵌小数据或 artifact 数据引用 | 点数超限时请求聚合/降级表格 | +| 导出 | PNG/SVG(实现可行时)、CSV | 通过受控 artifact/下载流程 | +| 可访问性 | 文本摘要、表格替代、ARIA、非颜色编码 | 不能只依靠颜色传达系列含义 | + +## 3. 地图 + +### 3.1 用户流程 + +1. Agent 通过 `present_map` 提交坐标/GeoJSON 及说明,地图块出现时显示标题、数据来源/attribution 和加载状态。 +2. 用户可平移/缩放、点选要素、查看属性、复制坐标、打开要素列表、导出 GeoJSON 或导出当前图像。 +3. 无网络、WebGL 不可用或未配置可用底图时,仍显示要素列表、边界/坐标和下载动作;地图本身不会阻塞消息阅读。 +4. 用户位置永远不是默认输入,只有用户点击清晰的“使用我的位置”后才请求平台权限;首期可以完全不提供该能力。 + +### 3.2 在线瓦片约束 + +地图块只引用 `tile_source_id`,由设置/管理员登记许可信息、attribution、允许域、网络可用性和缓存策略。模型不能构造任意瓦片地址或从 Markdown 嵌入在线地图。未配置服务时使用离线/空底图并明确提示。 + +## 4. 文件生成、预览与下载 + +### 4.1 产物卡流程 + +1. Agent/工具生成文件后,消息出现产物卡:文件名、类型、大小、生成来源、创建时间和预览状态。 +2. 支持格式显示“预览”;用户点击后才加载内容,避免历史列表解码大量文件。 +3. 用户点击“下载/另存为”后出现系统保存对话框;取消保持原状,成功 toast 显示目标文件名(不显示敏感完整路径)。 +4. 文件不存在、已过期、哈希异常、磁盘不足、无权限或解析失败时,卡片显示可恢复原因和建议动作;原文件存在时始终优先保留下载机会。 + +### 4.2 预览承诺 + +- 文本、Markdown、JSON、CSV:只读;支持搜索/复制/必要时截断提示。 +- PDF:分页只读渲染;不保证表单填写、签名、嵌入媒体或全部高级 PDF 特性。 +- XLSX:只读表格;不执行公式、宏、外部链接或数据连接。 +- DOCX:安全转换后的近似阅读;不承诺与 Microsoft Word 完全同版式。 +- 未支持、可执行、压缩、脚本、SVG/HTML、加密或异常文件:只显示 metadata 与下载。 + +### 4.3 保留与清理 + +默认保留期、会话删除后清理、手动“清理已过期产物”和导出包行为必须在设置中透明可见。清理前给出可恢复/不可恢复说明;当多个会话引用同一内容哈希时,不能提前删除仍有引用的对象。 + +## 5. 图片输出 + +### 5.1 功能 + +- 全模态模型/图像生成工具产出的 raster 图片在消息中按比例缩略展示。 +- 点击打开受控预览 Dialog,支持缩放、适配窗口、查看尺寸/大小/类型、下载和关闭。 +- 生成中显示确定的占位尺寸,完成后无布局跳动;失败时显示错误 notice,不在空白区域静默消失。 +- 历史消息重开后从 artifact metadata 恢复,不依赖短期 blob URL 或 provider 外链。 + +### 5.2 安全与质量限制 + +首期支持 PNG/JPEG/WebP/GIF。SVG 即使被声称为图像,也以通用下载产物处理。图片解码前检查 MIME、文件大小、像素和帧数;超限时不在主 WebView 解码。 + +## 6. 模型、工具和流式行为 + +### 6.1 输出路径 + +| 来源 | 允许产出 | 处理方式 | +|---|---|---| +| 普通模型文本 | Markdown | 原有 token 流保持不变 | +| 多模态/图像模型 | 图片 artifact + image block | provider adapter 验证并注册 | +| Agent | 图表、地图、文件、图片 | 仅窄 `present_*`/`create_artifact` 工具 | +| MCP | 经过权限与 ingress 检查的块/产物 | 标记 server/tool 来源并审计 | +| 用户上传 | 现有输入附件;后续可导入 artifact | 不自动作为 assistant 输出重新暴露 | + +### 6.2 流式状态 + +| 状态 | 用户所见 | 终态 | +|---|---|---| +| `pending` | skeleton/“正在生成” | ready、failed 或取消 | +| `ready` | 正常内容与操作 | 可预览/导出,遵守保留策略 | +| `failed` | 错误卡与建议 | 下载可用时继续显示下载 | +| `unsupported` | “当前版本不支持” | 显示安全摘要,可选原件下载 | +| `expired/deleted` | 不可用状态 | 不再尝试加载,提供原因 | + +停止生成仅影响当前消息的新块;历史已经完成的块不消失。重新生成创建新助手消息,不覆盖原消息中的图表、地图和文件。 + +## 7. 设置、权限和隐私 + +### 7.1 设置项 + +首期设置应至少提供: + +- 富内容总开关与每类 renderer 的 feature 状态(实验性时可见)。 +- artifact 存储位置说明、已用空间、保留期和手动清理。 +- 图片/文档/图表/地图的下载和预览上限说明。 +- 地图数据/瓦片服务的启用状态、许可/attribution、离线说明;密钥不显示、不交给模型。 + +### 7.2 权限原则 + +- 保存文件:每次通过系统对话框明确目标;不能 silently overwrite。 +- 地理位置:显式用户动作才请求,模型不可触发。 +- 网络瓦片:产品设置启用且对应服务已登记才可使用;没有“允许所有 URL”的开关。 +- Agent 外部生成:按现有工具审批与 Sandbox policy,不因产物需要展示而自动提升权限。 + +## 8. 错误与本地化契约 + +新增稳定错误码建议包括: + +```text +ARTIFACT_NOT_FOUND ARTIFACT_ACCESS_DENIED +ARTIFACT_TOO_LARGE ARTIFACT_STORAGE_QUOTA_EXCEEDED +ARTIFACT_TYPE_BLOCKED ARTIFACT_HASH_MISMATCH +ARTIFACT_EXPORT_CANCELLED ARTIFACT_EXPORT_FAILED +PREVIEW_UNSUPPORTED PREVIEW_PARSE_FAILED +PREVIEW_RESOURCE_LIMIT PREVIEW_CANCELLED +CONTENT_BLOCK_INVALID CONTENT_BLOCK_UNSUPPORTED +CHART_SPEC_INVALID MAP_SPEC_INVALID +MAP_TILE_SOURCE_UNAVAILABLE MAP_WEBGL_UNAVAILABLE +``` + +错误 payload 使用项目既有 `code`、`message_key`、参数、`retryable`、correlation ID 约定。用户界面翻译消息 key;不得从 Rust/Python 的自然语言错误文本推断行为。 + +## 9. 功能验收场景 + +1. 同一条回复包含 Markdown → 图表 → Markdown → 文件 → 图片,刷新/重开后顺序不变。 +2. 助手生成 CSV/PDF/图片均可在不授予 WebView 文件系统权限的情况下另存为。 +3. 图表/地图可由键盘访问并有表格/文本等价信息。 +4. 伪造 MIME、恶意 SVG、未知内容块、路径 traversal、跨会话 artifact ID、超大 PDF/XLSX 被拒绝或降级。 +5. 无 GPU/无网/解析器失败时,消息正文、工具调用和下载能力仍可使用。 +6. 停止、重生成、会话删除、Sidecar 断线后不存在错误归属的富内容,也无可访问的孤立临时资源。 diff --git a/docs/planning/rich-content-delivery/04-ui-ux-design.md b/docs/planning/rich-content-delivery/04-ui-ux-design.md new file mode 100644 index 0000000..396d8aa --- /dev/null +++ b/docs/planning/rich-content-delivery/04-ui-ux-design.md @@ -0,0 +1,134 @@ +# 富内容与产物交付 UI/UX 设计 + +> **用途:** 规定聊天内图表、地图、文件和图片组件的视觉语言、交互、可访问性与响应式行为。 +> **受众:** React UI、设计、测试和本地化维护者。 +> **最后审阅 / Last reviewed:** 2026-08-08 +> **状态:** Proposed;实施时必须同步现有 `docs/design/` 规范。 + +--- + +## 1. 继承的界面基线 + +本方案遵循项目的桌面 Agent 视觉语言:助手消息无大型气泡背景、内容横向铺满可用消息列;用户消息继续使用 `bg-muted` 的紧凑圆角气泡。富内容是消息正文中的“内容卡”,不能被设计成网页 dashboard、营销卡片或独立应用窗口。 + +实现时优先复用项目 token 和基础组件,特别是 `--surface-*`、`--border-*`、`--radius-ui-*`、`--ds-layer-*`、`OVERLAY_MOTION`、Dialog、Tooltip、DropdownMenu、Button 和 Sonner。不得硬编码另一套色板、夸张渐变、hover 缩放、弹跳动画或 emoji 图标。 + +相关权威规范: + +- [frontend-ui-guidelines.md](../../design/frontend-ui-guidelines.md) +- [shell-and-workspace-ui-spec.md](../../design/shell-and-workspace-ui-spec.md) +- [button-menu-design-spec.md](../../design/button-menu-design-spec.md) +- [现有 Chat 规范](../../ui/02-chat.md) 与 [Markdown 规范](../../ui/06-markdown-message-tools.md) + +## 2. 共同的 RichContentCard + +### 2.1 结构 + +```text +RichContentCard + header: icon + title + optional compact status + overflow actions + body: block-specific visualization / preview / image + footer: accessible summary, attribution or metadata + primary actions +``` + +- 位于 assistant 正文流内,默认 `my-4`;宽度为消息列,`min-w-0`,不突破聊天内容最大宽度。 +- 外层为低对比表面(`bg-muted/20` 或项目定义的 card surface)、`border-border/40`、`rounded-xl`、`overflow-hidden`。不得使用高饱和色作整卡背景。 +- Header 高度紧凑,左侧使用统一 Lucide 14–16px 图标;右侧操作使用现有 28px icon button/菜单。常用下载动作可明确显示,次要动作用溢出菜单。 +- Footer 仅在需要 attribution、生成元数据、错误或操作时展示;正文信息密度高时不重复标题。 + +### 2.2 状态 + +| 状态 | 视觉 | 行为 | +|---|---|---| +| 加载中 | 固定最小高度 skeleton + 简短文案 | 保留空间,禁止重复点击 | +| 完成 | 常规 surface/边框 | 操作可用、焦点可达 | +| 部分可用 | 中性提示 + 可下载/可查看数据 | 不用危险色误导为失败 | +| 失败 | `destructive` 文本/图标的小型 notice | 说明下一步,不清空同消息正文 | +| 不支持 | muted notice + 原件下载 | 不显示原始 JSON/堆栈 | +| 已过期 | muted/disabled metadata | 不发起重复加载 | + +加载、展开、预览只使用 opacity 和不超过 4–6px 的位移;遵循 `prefers-reduced-motion`。不能为流式块使用逐字/逐帧动效。 + +## 3. 图表 UI + +### 3.1 默认布局 + +```text +┌ [Chart] 销售趋势 [更多] ┐ +│ 2026 Q2 环比 +18%,增长主要来自华东。 │ +│ │ +│ 可缩放/悬停的图表画布 │ +│ │ +├ 数据表 导出数据 导出图像 12 条数据 ┤ +└────────────────────────────────────────────────────┘ +``` + +- 图面默认高度约 260–320px,窄窗口降低到 220px;固定/受控高度避免虚拟列表测量抖动。 +- 标题与结论在图面前,避免只让颜色和 tooltip 传递含义。 +- 图例支持键盘焦点与清晰 selected 状态;系列颜色用语义色板、pattern/marker 区分,深浅主题对比度足够。 +- “数据表”是可切换的正文区域而不是仅 hover tooltip;表格沿用现有 Markdown table 的横向滚动和操作语言。 +- 高密度数据必须把标签/tooltip 降噪,图例超过合理数量时优先显示可搜索的列表或数据表。 + +### 3.2 操作和键盘 + +- Tab 顺序:卡片操作 → 图例/可交互控件 → 数据表/导出。 +- `Enter`/`Space` 激活;`Escape` 关闭数据表、tooltip 锁定或 Dialog;不劫持消息列表的常规方向滚动。 +- 图表画布若无法提供完整键盘交互,必须通过 summary + 数据表提供等价可访问路径,并标记为 `aria-describedby`。 + +## 4. 地图 UI + +### 4.1 默认布局 + +地图卡沿用 RichContentCard,图面默认 300px,高宽变化时动态 `resize`,不可 overflow 到侧栏。Header 必须显式展示数据来源/attribution 入口;Footer 提供“要素列表”“复制坐标”“导出 GeoJSON”与可用时的“重置视图”。 + +选择要素时,在地图上使用克制的边框/halo,并在下面的可访问要素列表同步选中;不得只用 marker 颜色表示选择。地图或 WebGL 不可用时,直接显示列表、边界、坐标文本和原因提示,不显示永远旋转的 loader。 + +### 4.2 隐私与在线态 + +- 地图瓦片加载/离线状态在 footer 以小型状态文字表达,不弹 toast 打断对话。 +- 用户位置按钮若后续加入,属于显式主动作,有清晰权限解释;默认不出现追踪含义的图标/文案。 +- attribution 永远可见或一键可达;不使用模型生成的品牌/服务商 logo 作为依据。 + +## 5. 文件预览 UI + +### 5.1 产物卡 + +```text +┌ [FileTypeIcon] 月度分析.xlsx [更多] ┐ +│ XLSX · 248 KB · 由 Agent 生成 · 刚刚 │ +│ [预览] [下载] │ +└────────────────────────────────────────────────────────┘ +``` + +- 文件名单行截断但可 Tooltip/辅助文字查看全名;显示类型和大小,来源仅作辅助信息。 +- `预览` 是主操作(支持时),`下载` 保持可见;不支持预览时把“仅支持下载”的原因写清楚。 +- 预览在消息中显示轻量摘要,复杂 PDF/表格/DOCX 在二级 Dialog 中打开。Dialog 遵循现有最大宽度/高度、内部滚动和固定 footer 规则;不能让长文档把主页面拖到失去上下文。 +- PDF 页码、Sheet tabs、表格列冻结/横向滚动均由内容区负责,Dialog header/footer 不随内容滚动。 + +### 5.2 失败与可恢复性 + +解析失败、文件过大、已过期、权限不足分别给出不同 i18n 文案;下载仍可用时不得禁用。用户取消系统保存对话框不是错误,不显示 destructive toast。 + +## 6. 图片 UI + +- 消息中图片以 `max-width: 100%`、受控 `max-height`、`object-contain` 显示,预留尺寸防布局跳动;不裁掉信息性图像。 +- 图像点击进入预览 Dialog;header 显示文件名/尺寸,footer 提供缩放、适配和下载。关闭按钮有明确 label,`Escape` 可关闭并将焦点还给触发缩略图。 +- 重要图片 alt text 来自模型的结构化说明或用户给定文件名;没有可靠说明时用中性描述而不杜撰视觉内容。 +- GIF 等动图尊重减少动态偏好;超大图片在加载前显示轻量占位或缩略图,避免主线程卡顿。 + +## 7. 响应式、虚拟列表与性能 + +本产品是桌面优先,但必须适配最小窗口。卡片在窄宽度下改为纵向 action layout,保持按钮 44px 最小触控目标与清晰焦点。图表/地图不得产生聊天列横向滚动;表格和代码等需要横向查看的内容使用内部 `overflow-x-auto`。 + +消息虚拟列表中,富内容块要声明稳定的 loading 高度。图表/地图进入视口后再懒加载 renderer;离开视口可暂停昂贵渲染但不得丢失选择/缩放状态。PDF/XLSX 预览只在用户打开 Dialog 后加载。 + +## 8. 本地化与无障碍验收 + +- 所有按钮、Tooltip、状态、错误、单位、文件大小和时间均使用 i18n key;禁止在新增 JSX 写死中英文。 +- icon-only action 必须有 `aria-label`;每个图/地图有 title/summary;图片有 alt;失败消息用合适的 `role`/live region。 +- 正文最低对比度达到 4.5:1;选中、错误、离线不只依赖颜色。 +- 完成键盘流、屏幕阅读器摘要、深色/浅色、`prefers-reduced-motion`、最小窗口、100%/200% 缩放测试后才能标记 UI 阶段完成。 + +## 9. 设计文档同步规则 + +实现 UI 时,将可复用规则合并到最小范围的现有 `docs/design/` 文档:聊天布局进入 `shell-and-workspace-ui-spec.md` 或 `frontend-ui-guidelines.md`,按钮/菜单/Dialog 规则进入 `button-menu-design-spec.md`,Markdown/消息渲染细节同步 `docs/ui/06-markdown-message-tools.md`。更新对应“Last reviewed”日期,并在 [06-implementation-log.md](./06-implementation-log.md) 记录具体变更。 diff --git a/docs/planning/rich-content-delivery/05-filesystem-and-sandbox-research.md b/docs/planning/rich-content-delivery/05-filesystem-and-sandbox-research.md new file mode 100644 index 0000000..1abfd42 --- /dev/null +++ b/docs/planning/rich-content-delivery/05-filesystem-and-sandbox-research.md @@ -0,0 +1,131 @@ +# 富内容功能的文件系统与 Sandbox 调研结论 + +> **用途:** 回答“实现图表、地图、文件预览/下载和图片显示是否需要文件系统、Sandbox,以及应如何接入”的决策问题。 +> **受众:** 架构、安全、Rust、Sidecar 和发布维护者。 +> **最后审阅 / Last reviewed:** 2026-08-08 +> **状态:** 调研结论已纳入实施计划;需在实现 Spike 中验证 Tauri URI 与三平台行为。 + +--- + +## 1. 执行结论 + +### 1.1 文件系统:需要,但不需要给 WebView 通用文件系统权限 + +生成文件、图片、PDF/Office 预览缓存、哈希校验、保留清理和用户另存为都需要可靠的本地字节存储。因此必须增加 **Rust 持有的应用专属 Artifact Store**。这不是 `@tauri-apps/plugin-fs` 的使用场景:项目已有自定义 Rust `fs_*` command,并且现行 capability/CSP 审计明确主 WebView 不应拥有通用 FS 权限。 + +Tauri 官方文档也区分了 Rust 侧可直接使用 `std::fs`/`tokio::fs` 与前端 FS plugin,并说明 plugin 的危险命令和 scope 默认被阻断。故推荐继续由 Rust application service 实现,只为明确的 artifact read/export 暴露窄 command/URI,保持默认 capability 不增加 `fs:*`。来源见 [Tauri File System](https://v2.tauri.app/plugin/file-system/) 与 [Tauri Permissions](https://v2.tauri.app/security/permissions/)。 + +### 1.2 Sandbox:展示功能本身不依赖完整 OS Sandbox,但内容安全不可省略 + +纯 Markdown、受限图表 spec、静态 GeoJSON、raster 图片显示和已存档文件下载并不运行不可信宿主程序,因此不应等待完整跨平台 Sandbox 才交付。然而它们仍必须有:MIME/magic 检查、配额、哈希、解析上限、URI 授权、严格 CSP、无脚本 schema 和安全降级。这是 **内容安全面**,不能拿“未来有 Sandbox”取代。 + +完整 OS Sandbox 是以下场景的硬依赖或强烈建议: + +- Agent/Skill/MCP 使用 shell、编译器、图像/Office 转换器或其他外部程序产生文件; +- 不可信文件交给原生二进制解析器/转换器处理; +- 需要网络访问、地理编码、远程瓦片或第三方生成服务; +- 解析器需要隔离 CPU、内存、文件系统、环境变量和子进程树。 + +这些路径必须复用已有 [Sandbox ADR](../../architecture/SANDBOX_TECH_SELECTION.md) 的 `SandboxBroker`、平台 provider、网络 policy、审批与审计;不能因为“只是生成预览”退回直接继承宿主环境的 subprocess。 + +## 2. 按功能的决策矩阵 + +| 功能 | 受控本地文件系统 | 内容安全面 | OS Sandbox | 网络/CSP | 首期决策 | +|---|---:|---:|---:|---:|---| +| Markdown/Mermaid | 否 | 是(现有 Markdown 防护) | 否 | 否 | 保持现状 | +| 统计图 | 可选(数据导出时需要) | 是,受限 ChartSpec | 否 | 否 | 本地 renderer + 数据表 | +| 静态 GeoJSON 地图 | 可选(GeoJSON 导出/缓存) | 是,受限 MapSpec/要素数 | 否 | 否 | 先支持离线数据 | +| 远程瓦片地图 | 是(缓存) | 是 | 不一定 | 是,必须受控 | registry + Rust broker 后再启用 | +| 模型 raster 图片 | 是 | 是(MIME/像素/解码限制) | 否 | 否 | Artifact Store + 图片 viewer | +| 生成文本/CSV | 是 | 是(大小/编码) | 否 | 否 | 本地预览 + 下载 | +| PDF/XLSX/DOCX 预览 | 是 | 是(解析配额) | 视解析器而定 | 否 | 本地 parser;高风险/原生转换后接 Sandbox | +| HTML/SVG/可执行文件 | 是(下载) | 是 | 是(若要处理) | 否 | 首期仅下载,禁止内联预览 | +| Agent/Skill/MCP 外部生成 | 是 | 是 | **是** | 可能 | 进入已有 Sandbox 阶段 | + +## 3. 当前项目与建议边界 + +### 3.1 当前安全基线 + +当前 `src-tauri/capabilities/default.json` 只提供事件、外链、dialog、clipboard、自定义 command 和窄 terminal runtime;`src-tauri/tauri.conf.json` 的生产 CSP 仅允许本地/asset/blob/data 图像和本地 IPC。`docs/guides/tauri-capability-csp-audit.md` 进一步确认 WebView 不应获得通用 FS、HTTP、Shell execute/spawn。 + +此基线是本功能的优势,不应为“容易预览文件”而撤销。新增资源路径应是如下闭环: + +```text +模型/工具字节 + -> Rust ingress (validate/hash/quota) + -> app-owned artifact store + -> ArtifactRecord + message block + -> scoped URI / narrow read DTO + -> React preview + +React download click + -> artifact_id command + -> native Save dialog + -> Rust verified copy +``` + +前端不得得到工作区、`~/.misakax`、文件缓存或用户选择文件夹的原始可拼接路径。 + +### 3.2 URI 方案调研 + +Tauri 的 `asset:` protocol 可将磁盘文件传给 WebView,但必须在 `app.security.assetProtocol` 启用并为精确文件树定义 scope;官方文档特别警告不要把 allow 扩为 `$HOME/**/*` 或 `**/*`。对动态用户选择目录还需 persisted-scope,而这正是本设计要避免暴露的能力。来源:[Asset protocol scope](https://v2.tauri.app/security/asset-protocol/)。 + +建议做 R1 Spike 比较两条路径: + +| 方案 | 优点 | 风险/约束 | 建议用途 | +|---|---|---|---| +| 窄 `asset:` scope | 已有 CSP 支持,适合本地图片/PDF资源 | 静态 scope,不能细化到会话授权;必须谨慎处理 dot directory | artifact root 固定、公共只读预览 | +| `misakax-artifact:` 自定义协议 | opaque ID、可检查 session/revision/TTL、可加 range 与审计 | 需实现 HTTP response/MIME/缓存和跨平台测试 | 默认优先;尤其文件/PDF/权限敏感场景 | + +Tauri 2 支持注册自定义 URI protocol,并有异步版本避免阻塞主线程;Windows custom scheme 与 WebView2 版本有发布约束,需加入 installer/三平台验收。来源:[Tauri 2.0 release](https://v2.tauri.app/blog/tauri-20/)、[Windows installer minimum WebView2](https://v2.tauri.app/distribute/windows-installer/)。 + +## 4. 图表、地图与 WebView 安全 + +### 4.1 图表 + +Apache ECharts 可使用 `dataset` 与 `series.encode` 分离数据和视觉编码,适合将受限 `ChartSpec` 编译为图表 option。其 ARIA 组件需显式加载,才能生成辅助技术描述;首期必须同时提供数据表而不能只依赖图形。来源:[ECharts Dataset](https://echarts.apache.org/handbook/en/concepts/dataset/) 与 [ECharts ARIA](https://echarts.apache.org/handbook/en/best-practices/aria/)。 + +安全要求:不接受 `formatter` function、任意 callback、HTML tooltip 或网络数据 URL。ECharts 是渲染器,不是模型输出协议。 + +### 4.2 地图 + +MapLibre GL JS 是浏览器 WebGL 地图渲染库,支持 style/source/layer,但官方文档说明它依赖 `worker-src blob:`、`child-src blob:`、`img-src data: blob:`,严格 CSP 环境可使用专用 CSP worker bundle。项目当前 CSP 已有 worker/child blob 基础,仍需在 R4 Spike 测试本地 bundle、懒加载、WebGL 失败和 CSP 违反。来源:[MapLibre GL JS documentation](https://maplibre.org/maplibre-gl-js/docs)。 + +真正的额外风险是瓦片/style 的网络请求:若在 WebView 直接允许宽泛 `https:`,模型或数据源可诱导网络请求并扩大 CSP。故首期只处理本地 GeoJSON;后续瓦片只能引用 `tile_source_id`,由 Rust broker/custom URI 映射到已审批的 provider、密钥与缓存,保持主 WebView `connect-src` 的最小化。 + +## 5. 文件预览的安全边界 + +### 5.1 本地解析优于在线查看器 + +将 PDF/DOCX/XLSX 上传到在线查看器会泄露聊天产物和用户数据、受外部 CSP/iframe 限制、并引入服务可用性与合规依赖。因此不作为默认选项。PDF.js 的 display/viewer 层可用于构建本地浏览器预览,但需要打包本地资源、worker 与 page/timeout 限制;PDF.js 文档也指出本地 `file://` 不适合作为 worker viewer 加载方式。来源:[Mozilla PDF.js Getting Started](https://mozilla.github.io/pdf.js/getting_started/?lang=en)。 + +XLSX 可从受控 ArrayBuffer/Uint8Array 读取;浏览器环境不应按文件名任意读取本地路径。首期解析后只渲染值,不执行公式、宏、外部链接。来源:[SheetJS Data Import](https://docs.sheetjs.com/docs/solutions/input/) 与 [SheetJS Parsing](https://docs.sheetjs.com/docs/api/parse-options/)。 + +### 5.2 不可信活跃内容 + +HTML、SVG、JS、可执行文件、Office macro 和嵌入对象都可能含主动内容。首期只允许下载,不在聊天主 WebView 解析或 inline。如果后续确有需求,必须新建独立“内容预览 sandbox”设计:隔离 webview/capability、无 Tauri IPC、禁止宿主凭据和网络,或使用不带 `allow-same-origin` 的最小 sandboxed iframe;但 MDN 明确指出 iframe sandbox 一旦能在框架外打开内容就失效,因此不能把 iframe 当作唯一防线。来源:[MDN iframe sandbox](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe)。 + +当前生产 CSP 的 `frame-src 'none'` 是有意的安全基线。任何未来 iframe 需求都要单独 ADR、CSP 差异审计和攻击测试,不可为 DOCX/HTML 预览直接放宽。 + +## 6. 与既有 Sandbox 计划的合并方式 + +不复制或重新发明现有 Sandbox B0–B7;新增以下挂接点: + +1. **R0 / Sandbox B1:** `ContentSafetyPolicy` 与 `SandboxPolicy` 各自独立,均由 Rust 领域层构造并审计。前者保护字节/renderer,后者保护执行/进程。 +2. **R2 / Sandbox B0:** 对原生解析器或 converter 建立攻击 fixture:path traversal、symlink/junction、压缩炸弹、超页/超像素、子进程、网络尝试、资源耗尽。 +3. **R5 / Sandbox B5:** Agent/Skill/MCP 的 `create_artifact` 若依赖外部命令,使用 authenticated execution bridge → `ExecutionService` → `SandboxBroker`,不能直连 Sidecar 本地 shell。 +4. **R4b / Sandbox B6:** 地图瓦片与地理编码归类为网络 policy,记录域名、批准、缓存与审计;即使不运行 shell,也不能让 WebView 任意出网。 +5. **R6 / Sandbox B7:** 严格 provider 缺失时,禁用需要外部执行的预览/生成器并给出诊断,绝不降级为 full-access。 + +## 7. 必须纳入计划的验证项 + +- [ ] asset/custom URI 不能读取 artifact root 以外的任何文件,不能用 `..`、编码路径、符号链接、junction 绕过。 +- [ ] 任何无 artifact ID、无会话归属、过期 revision、错误 MIME 的请求均失败且不泄露真实路径。 +- [ ] `dialog:allow-save` 下载取消、同名、Unicode、长路径、磁盘不足、只读目录在三平台行为可解释。 +- [ ] PDF/XLSX/DOCX/图片畸形样本、解压炸弹、超尺寸、超时、取消不会卡死 UI/主进程。 +- [ ] Chart/Map spec 不存在可执行 function、HTML、任意 URL 注入;图表/地图不放宽主 WebView CSP。 +- [ ] 触发外部 converter、Agent shell、Skill/MCP helper 时只有 Sandbox Broker 路径可用。 + +## 8. 最终建议 + +将 “Artifact Store + 内容安全策略 + 窄 URI/导出” 作为 R0/R1 的明确前置项;将 “Sandbox 对外部执行、网络和高风险解析器的接入” 作为 R2/R5/R6 的依赖项。这一拆分既能尽快交付安全的图片/文件/图表/静态地图,又不淡化已有跨平台 Sandbox 方案必须完成的真实隔离工作。 diff --git a/docs/planning/rich-content-delivery/06-implementation-log.md b/docs/planning/rich-content-delivery/06-implementation-log.md index 0efe517..d22d4c2 100644 --- a/docs/planning/rich-content-delivery/06-implementation-log.md +++ b/docs/planning/rich-content-delivery/06-implementation-log.md @@ -3,7 +3,7 @@ > **用途:** 记录实际实施、验证、决策变更、风险与下一步,保证人类和 AI Agent 接手时可追溯。 > **受众:** 所有实施者与评审者。 > **最后审阅 / Last reviewed:** 2026-08-09 -> **状态:** R0–R3 已通过远程全量 CI。R4 地图已完成本地验证,待阶段提交、推送与远程 CI。 +> **状态:** R0–R4 已通过各自的远程全量 CI;R5、R6 尚未开始。 --- @@ -24,7 +24,7 @@ | R1 ArtifactService/图片/下载 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `53a079d`;[CI #31272842590](https://github.com/knqiufan/MisakaX/actions/runs/31272842590) 的 8 项检查全绿 | | R2 文件预览 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `2e979e1`;[CI #31285793427](https://github.com/knqiufan/MisakaX/actions/runs/31285793427) 的 8 项检查全绿 | | R3 图表 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `ee6eea7`;[CI #31287278455](https://github.com/knqiufan/MisakaX/actions/runs/31287278455) 的 8 项检查全绿 | -| R4 地图 | 本地验证完成,待门禁 | 当前实施者 | 2026-08-09 | — | 受限本地 GeoJSON、MapLibre fallback 与 ArtifactService 导出;待 commit/push/CI,R4b 不在范围内 | +| R4 地图 | 已完成 | 当前实施者 | 2026-08-09 | 2026-08-09 | `0a64123`;[CI #31288007260](https://github.com/knqiufan/MisakaX/actions/runs/31288007260) 的 8 项检查全绿;R4b 不在范围内 | | R5 Agent/Sidecar/MCP | 未开始 | 待分配 | — | — | 依赖 Phase 4 真正对话链路;通过阶段门禁后完成 | | R6 加固/发布 | 未开始 | 待分配 | — | — | 三平台/沙箱 gate;通过阶段门禁后完成 | @@ -207,11 +207,11 @@ - **代码审查:** 核对 renderer registry 已指向 `MapBlockRenderer`,动态加载只发生在块渲染时;数据来源/attribution 位于卡片 header,视图可复位;WebGL/MapLibre 错误不会影响相邻块;Clipboard 使用 Tauri 插件;导出临时 artifact 在保存流程结束后 expire。命令已同时出现在 `invoke_handler`、AppManifest 和最小权限白名单,权限基线测试覆盖该集合。 - **验证:** `cargo fmt --check` ⇒ pass;`cargo test --all-features --lib map` ⇒ 3 passed;`cargo test --all-features --lib artifact` ⇒ 8 passed;`cargo test --all-features --test security_config_baseline_tests` ⇒ 5 passed;`cargo clippy --all-targets --all-features -- -D warnings` ⇒ pass;`npm test -- --run` ⇒ 39 files / 273 passed;`npm run build` ⇒ pass(既有大动态 chunk warning)。 - **未验证:** 未在三平台真实 GPU/WebGL、屏幕阅读器、窗口缩放或实际保存对话框中手工回归;JSDOM 的 canvas diagnostic 不影响测试 exit 0。远程 CI 尚未执行。 -- **Git:** 待以独立 R4a commit 推送至 `codex/rich-content-r0-r4`。 -- **远程 CI:** 待非强制 push 后触发并完成 8 项 required checks;在全绿前 R4 不标记完成。 +- **Git:** `0a641237c9f8cfe582d1809fdcb7424f495394ab`(`feat(rich-content): complete r4 local GeoJSON maps`)已非强制推送至 `origin/codex/rich-content-r0-r4`。 +- **远程 CI:** [CI #31288007260](https://github.com/knqiufan/MisakaX/actions/runs/31288007260) completed/success,Rust、Frontend、三平台 Terminal Runtime 与三平台 Tauri Build 共 8 项检查全绿;R4a 阶段门禁已满足。 - **风险/回滚:** 回退 R4a commit 即恢复 `map` 的不可执行 notice fallback;不会放宽 CSP 或现有通用文件/网络能力。MapLibre bundle 增量仅在地图 renderer 动态加载时下载。 - **文档同步:** `docs/design/frontend-ui-guidelines.md` §4.6.x.1;本实施记录。 -- **下一步:** 审查 R4a 暂存差异、提交、非强制推送并等待远程 CI 全绿;随后更新阶段看板与 R0–R4 交接文档。 +- **下一步:** 更新阶段看板与 R0–R4 交接文档;R4b 以及 R5/R6 必须另行立项并分别通过同一阶段门禁。 ## 后续记录模板 diff --git a/docs/planning/rich-content-delivery/07-ai-coding-execution-guide.md b/docs/planning/rich-content-delivery/07-ai-coding-execution-guide.md new file mode 100644 index 0000000..5331323 --- /dev/null +++ b/docs/planning/rich-content-delivery/07-ai-coding-execution-guide.md @@ -0,0 +1,190 @@ +# 富内容与产物交付:AI Coding 执行说明 + +> **用途:** 让后续 AI Coding Agent 能在不重新猜测项目状态和安全边界的情况下继续实施。 +> **受众:** AI Coding Agent、开发者与代码评审者。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **状态:** R0–R4 已依本指南完成;R5、R6 尚未启动。阶段实现和门禁证据见 [实施过程记录](./06-implementation-log.md) 与 [R0–R4 交接](./09-r0-r4-handoff.md)。 + +--- + +## 1. 当前事实与目标 + +MisakaX 是 Tauri 2 + React 19 + TypeScript + Rust 2021 + Python 3.11 Sidecar 的桌面 Agent 客户端。当前聊天已支持 Markdown/Streamdown、Mermaid、数学公式、工具调用、图片**输入**附件和流式文本,但 assistant 消息仍以单一 `content: string` 为主,没有图表、地图、生成文件预览/下载或模型**输出**图片的类型化协议。 + +本工作流的目标是把 assistant 回复变成有序的、版本化 `ContentBlock` 列表,并通过 Rust `ArtifactService` 处理图片和文件。完整定义见 [00-overall-implementation-plan.md](./00-overall-implementation-plan.md) 与 [02-architecture-design.md](./02-architecture-design.md)。 + +## 2. 开始任何代码任务前的阅读顺序 + +1. 本目录的 [README.md](./README.md)、[00-overall-implementation-plan.md](./00-overall-implementation-plan.md)、[01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md)。 +2. 本目录中与本次任务对应的架构、功能、UI、安全文档;不要只读任务标题就开始写代码。 +3. 项目根 `AGENTS.md`,以及要修改路径范围内的规则/规范。 +4. [开发状态与续做指南](../../project/DEVELOPMENT_STATUS.md),确认 Phase 3/4 当前真实前置条件。 +5. 若涉及安全、文件或执行: + - [Tauri Capability/CSP 审计](../../guides/tauri-capability-csp-audit.md) + - [Sandbox ADR](../../architecture/SANDBOX_TECH_SELECTION.md) + - [Sandbox 实施计划](../SANDBOX_IMPLEMENTATION_PLAN.md) +6. 若涉及 UI: + - [frontend-ui-guidelines.md](../../design/frontend-ui-guidelines.md) + - [shell-and-workspace-ui-spec.md](../../design/shell-and-workspace-ui-spec.md) + - [button-menu-design-spec.md](../../design/button-menu-design-spec.md) + - [Chat UI](../../ui/02-chat.md)、[Markdown/消息规范](../../ui/06-markdown-message-tools.md) + +实施前用 `git status --short` 检查工作树。不要覆盖用户已有的无关修改;必要时在实施记录中标记冲突和决策。 + +## 3. 不可违反的约束 + +### 3.1 安全 + +- **禁止**添加 `@tauri-apps/plugin-fs` 或在 capability 中给予通用 `fs:*`、`http:*`、Shell execute/spawn 权限来快速实现预览/下载。 +- **禁止**让 React 接受/拼接绝对文件路径、`file:` URL、任意 artifact URI、任意远程 URL 或模型指定的保存路径。 +- **禁止**让模型/Agent 传入原生 ECharts option function、HTML/JS/CSS、地图 tile URL、SVG/HTML inline 内容、shell argv 或 Tauri scope。 +- **禁止**为地图或预览把生产 CSP 宽化为任意 `https:`、`*`、`unsafe-eval`、任意 `frame-src`。所有 CSP/capability 改动均需专门测试与文档更新。 +- **禁止**在 Sandbox 不可用时,将 Agent/Skill/MCP 的外部 converter 或 shell 自动降级到宿主直接执行。 +- **禁止**把二进制/大 Base64 写进 `messages.content` 或无限 JSON DTO;用 artifact store + ID 引用。 +- **禁止**把在线 Office/第三方网页嵌入当默认预览方案,避免数据外流和 iframe/CSP 风险。 + +### 3.2 架构与兼容 + +- Rust 是 artifact 身份、权限、路径、MIME、哈希、配额、导出、清理和审计的唯一权威;React/Python 不能复制安全判断。 +- 新消息块必须有 `schema_version`、稳定 `block_id`、消息内 `position`、状态和 safe fallback。 +- 旧 `messages.content`、`attachments`、`tool_calls`、流事件、导入/导出必须双读或有兼容 adapter;不得一次性删除旧路径。 +- renderer/previewer/provider normalizer 使用 Registry + Strategy + Adapter,不做跨层巨型 `switch` 或“一个万能 RichMessage 组件”。 +- 所有新异步事件至少携带 session/message/block identity 和 generation/revision;UI 必须忽略迟到事件。 +- UI 中没有硬编码文案,新增 key 同时写入 `src/locales/zh-CN/` 和 `src/locales/en/`。 + +## 4. 推荐代码阅读地图 + +| 任务 | 先读的当前文件 | +|---|---| +| 消息 DTO/存储 | `src/lib/ipc/types.ts`、`src/lib/ipc/chat.ts`、`src/stores/chat-store.ts` | +| 流式投影 | `src/hooks/use-stream-listener.ts`、`src-tauri/src/services/llm/streaming.rs`、`services/sidecar_sse.rs` | +| 消息 UI/Markdown | `src/components/chat/message/MessageItem.tsx`、`src/components/chat/markdown/MessageResponse.tsx`、`markdown-components.tsx` | +| 图片/附件兼容 | `src/components/chat/composer/attachmentUtils.ts`、`AttachmentPreview.tsx`、`services/llm/backend.rs` | +| 数据库/会话导入 | `src-tauri/src/db/migrations.rs`、`db/models.rs`、`db/repository/message_repo.rs` | +| Tauri 权限/资源 | `src-tauri/capabilities/default.json`、`src-tauri/tauri.conf.json`、`src-tauri/src/lib.rs` | +| 现有文件边界 | `src-tauri/src/commands/fs_explorer.rs`、`src/lib/ipc/fs.ts` | +| Agent/Sidecar | `agent/app/models.py`、`routers/agent.py`、`stream_content.py`、`src-tauri/src/services/sidecar_*` | + +不要仅凭旧文档假定 Sidecar 已接管主对话。当前开发状态明确它是后续 Phase 4 的主线;先以现有 Rig + Tauri event 链路建立兼容合同,再接入 Sidecar adapter。 + +## 5. 分阶段执行模板 + +### R0:先建契约和测试 + +1. 写/更新 TypeScript 与 Rust DTO fixture 测试,覆盖 legacy message、未知 block、非法 schema、顺序与状态。 +2. 设计 SQLite migration 和 rollback/compat 行为;审查索引、导入/导出、会话删除。 +3. 新增 feature flag,默认关闭 UI 切换;不要在本阶段引入重型 renderer 依赖。 +4. 跑精准测试,再跑受影响的前端/Rust 检查;记录结果。 + +### R1:Artifact Store Spike 后再做实现 + +1. 在不改 capability 宽度的条件下实现小型 URI Spike;比较 scoped `asset:` 与 custom protocol。 +2. 用攻击样本验证路径、MIME、哈希、会话归属与导出取消。 +3. 选择方案写入 [06-implementation-log.md](./06-implementation-log.md) 的决策记录,再实现 ArtifactService、metadata、图片和下载 UI。 + +### R2–R4:按 renderer 独立垂直切片交付 + +- 每增加一种 previewer/renderer,先建立安全 schema 和 fallback,再增加 UI。 +- 重型库动态 import;不存在时与加载失败时可阅读消息、可下载原件。 +- R4 远程瓦片是单独子阶段,不得随静态地图一起悄悄修改 CSP/network。 + +### R5–R6:后接真实 Agent、MCP 与 Sandbox + +- 将 provider/Sidecar/MCP 输出收敛到同一 `RichOutputAdapter` 和窄工具契约。 +- 对外部命令/转换器,先验证相应 Sandbox provider;没有 strict guarantee 就 disabled + diagnostic。 +- 完成三平台、离线、资源/恶意样本、安全回归,再标记发布就绪。 + +## 6. 验证命令与最低测试矩阵 + +根据变更范围选择,而不是无差别执行所有慢任务。项目不应在日常工作前运行 `cargo clean`。 + +```powershell +# 前端类型与打包 +npm run build + +# 前端测试(优先运行相关 test;必要时全量) +npm test + +# Rust:在 src-tauri/ 下,优先增量精准验证 +cargo check +cargo test --test +cargo nextest run --all-features --profile ci # 提交前,若已安装 + +# Sidecar:仅改动 Python 或协议时 +cd agent +python -m pytest +``` + +每个富内容阶段的最低验收还包括: + +- 旧 Markdown、现有用户图片输入、工具调用、流式停止/重新生成、消息分页、导入/导出。 +- 深色/浅色、窄窗口、键盘、屏幕阅读器摘要、减少动态偏好。 +- URI 越权/路径 traversal/MIME confusion/超限/取消/文件缺失。 +- 若引入网络或外部执行,CSP/capability diff 与 Sandbox policy 回归。 + +## 7. 阶段完成门禁:代码审查、本地验证、Git 与远程 CI + +**R0–R6 的每个阶段都是一个独立交付单元。未完整通过本节门禁前,严禁启动下一阶段的代码开发、依赖接入或迁移。** 下一阶段可以做不改代码的调研和计划细化,但不得开始实现。 + +### 7.1 固定顺序 + +阶段任务看似完成后,严格按以下顺序执行: + +1. **收口阶段范围。** 确认变更只覆盖当前 R 阶段;将临时调试、无关格式化、无用依赖和未完成实验从提交中移除或拆开。 +2. **代码审查通过。** 完成变更差异审查和当前阶段的安全/兼容性检查:查看 `git diff`、调用链、迁移、错误处理、i18n、测试、CSP/capability、日志脱敏及本目录的验收项。仓库/团队要求人工 reviewer 时,必须取得实际批准;AI 不得虚构或自行替代人工审批。没有人工审批要求时,在实施记录中写明已完成的 self-review 清单和发现/修复结果。 +3. **本地测试通过。** 运行第 6 节中所有与改动相关的精准测试、构建及安全回归;若当前阶段改变跨层协议、迁移、CSP/capability 或共享聊天渲染,必须补跑相应全量测试。所有结果必须为 pass;不可把已知失败、跳过、超时或“理论上应通过”记作通过。 +4. **更新实施证据。** 在 [06-implementation-log.md](./06-implementation-log.md) 记录实际修改、代码审查结果、本地命令及输出摘要、未验证项、风险和下一步;涉及 UI 时同步规定的 `docs/design/` 文档。 +5. **提交当前阶段。** 用一个可审阅、可回滚的 Conventional Commit 提交当前阶段已验证变更。提交前再次检查 `git status --short`,不得把用户无关改动、凭据、构建产物、缓存或本地测试数据纳入提交。 +6. **推送提交。** 以非强制方式推送当前分支到已配置的远程仓库;首次推送使用 upstream。记录 commit SHA、分支和远程 URL/CI 运行链接(如可获取)。 +7. **等待远程 CI 全绿。** 只以远程仓库对该 commit/分支报告的 required CI 状态为准。所有必需检查都成功、没有 queued/running/pending/neutral/未配置项,并且所需人工审查已满足后,才可把当前阶段标记为“完成”并启动下一阶段。 + +### 7.2 Git 操作约束 + +```powershell +# 收口和审查当前阶段差异 +git status --short +git diff --check +git diff --staged + +# 阶段通过本地门禁并更新记录后 +git add +git commit -m "feat(rich-content): complete r1 artifact delivery" +git push -u origin # 仅首次;后续使用 git push +``` + +- 分支遵循仓库 `codex/` 前缀和项目既有分支/PR 规则;未经明确授权不得推送到受保护主分支,也不得使用 `--force`、`--force-with-lease` 或改写已推送历史。 +- 一个阶段有多次 CI 修复时,修复仍归属**同一阶段**:每次修复都要重新执行代码审查和受影响本地测试,再以新的、清晰的 fix commit 推送。不要通过 `commit --amend` 改写已被远程 CI 检查的提交。 +- 提交说明应体现阶段、实际交付和风险边界,例如 `feat(rich-content): complete r3 chart renderer`、`fix(rich-content): handle expired artifact previews`;不要使用含糊的 `update`、`wip` 或把多个阶段混在一个提交中。 + +### 7.3 远程 CI 失败、不可用或等待中的处理 + +| 远程状态 | 当前阶段状态 | 允许动作 | 禁止动作 | +|---|---|---|---| +| queued/running/pending | 待 CI | 监控运行、整理证据、修复 CI 明确暴露的当前阶段问题 | 启动下一阶段实现 | +| failed | CI 修复中 | 定位失败,修复当前阶段,重复 7.1 的审查/本地测试/提交/推送 | 以本地 pass 忽略远程失败;跳到下一阶段 | +| required review 未批准 | 待审查 | 等待/请求实际 reviewer;补充说明 | 虚构批准或自行绕过分支保护 | +| CI 未配置/无法查询 | 阻塞 | 在实施记录标明远程、commit、原因并请求用户/仓库维护者提供 CI 验证方式 | 自行视为 CI 已通过或进入下一阶段 | +| all required checks passed | 已完成 | 更新阶段看板和实施记录,启动下一阶段 | — | + +远程 CI 的验证应使用仓库实际提供的状态页、PR checks 或已配置的连接器/CLI;“`git push` 返回成功”仅代表上传成功,**不是** CI 通过。等待期间若用户要求停止、切换任务或 CI 需要人工权限,记录当前 commit/状态后安全停下。 + +## 8. 依赖选择与研究要求 + +所有新增依赖先看本项目锁定版本和许可证,再用官方文档验证当前 major/minor API。建议评估而不是在未验证前承诺: + +- 图表:Apache ECharts,显式 ARIA 组件、dataset/encode 方案。 +- 地图:MapLibre GL JS,本地 bundle、CSP worker 与 WebGL 回退。 +- PDF:PDF.js,本地 viewer/worker,不走 `file:` 或在线服务。 +- XLSX:可从 `ArrayBuffer` 读取的本地解析器;禁止公式/宏执行。 + +详细的官方来源和结论见 [08-research-sources.md](./08-research-sources.md)。若候选依赖改变 CSP、WebWorker、WASM、许可证或 native binary 边界,必须先做小型 Spike 和安全评审。 + +## 9. UI 文档同步与交付 + +只要实施了 UI,除本目录记录外,必须按项目规则把可复用的规范同步到合适的 `docs/design/` 文件并更新 Last reviewed 日期。不能只把规则留在代码注释或 PR 描述中。 + +每次完成一个工作包,更新 [06-implementation-log.md](./06-implementation-log.md):修改范围、审查结果、本地验证、commit/push/远程 CI 证据、未验证项、迁移/回滚、安全影响、下一步。只有远程 CI 全绿后才可把该阶段更新为完成。最终交付前核对 [00-overall-implementation-plan.md](./00-overall-implementation-plan.md) 第 7 节成功标准。 + +## 10. 交接提示 + +如任务只要求文档、调研或设计,不要擅自修改生产代码/依赖/CSP。若任务要求实施而关键产品选择缺失(例如保留期、地图数据提供商、在线网络同意、文件格式范围),先从已有设置、需求或本目录决策门中查找;仍无法确定且选择会扩大权限或影响用户数据时,停下并请求产品决策。 diff --git a/docs/planning/rich-content-delivery/08-research-sources.md b/docs/planning/rich-content-delivery/08-research-sources.md new file mode 100644 index 0000000..82ed303 --- /dev/null +++ b/docs/planning/rich-content-delivery/08-research-sources.md @@ -0,0 +1,60 @@ +# 富内容与产物交付调研资料与本地证据 + +> **用途:** 保存本方案的可追溯依据,帮助后续实现者在依赖/API 变更时重新核验。 +> **受众:** 架构、开发、安全和 AI Coding Agent。 +> **最后审阅 / Last reviewed:** 2026-08-08 +> **调研日期:** 2026-08-08 + +--- + +## 1. 外部一手资料 + +| 主题 | 来源 | 方案采用的结论 | +|---|---|---| +| Tauri Rust FS 与前端 FS scope | [Tauri File System](https://v2.tauri.app/plugin/file-system/) | Rust 可使用 `std::fs`/`tokio::fs`;前端 FS plugin 的危险权限与 scope 默认受限。Artifact Store 应保留在 Rust,不开放通用 WebView FS。 | +| Tauri permission/capability | [Permissions](https://v2.tauri.app/security/permissions/)、[Capabilities](https://v2.tauri.app/security/capabilities/)、[Command scopes](https://v2.tauri.app/security/scope/) | capability 是 WebView 权限边界;deny 高于 allow;自定义 command 必须自行正确执行 scope。 | +| Tauri CSP | [Content Security Policy](https://v2.tauri.app/security/csp/) | CSP 应尽可能窄,避免远端脚本和不可信资源;不要为 renderer 添加宽泛 CDN/`unsafe-eval`。 | +| Tauri asset protocol | [Asset protocol scope](https://v2.tauri.app/security/asset-protocol/) | asset protocol 必须启用且有精确 scope;禁止 `$HOME/**/*`/`**/*` 式宽范围;动态目录不应成为默认方案。 | +| Tauri custom protocol/发布 | [Tauri 2.0 release](https://v2.tauri.app/blog/tauri-20/)、[Windows installer](https://v2.tauri.app/distribute/windows-installer/) | 可注册异步 custom URI protocol;Windows custom protocol 功能需在 WebView2/安装包测试中确认。 | +| ECharts 数据和无障碍 | [Dataset/encode](https://echarts.apache.org/handbook/en/concepts/dataset/)、[ARIA best practices](https://echarts.apache.org/handbook/en/best-practices/aria/) | 使用受限数据/编码 schema;显式引入 ARIA 组件,并提供表格替代。 | +| MapLibre 与 CSP | [MapLibre GL JS documentation](https://maplibre.org/maplibre-gl-js/docs) | MapLibre 使用 WebGL/workers,并有 CSP bundle 指引;远程 style/tile 将带来网络与 CSP 设计,不可由模型给 URL。 | +| PDF 本地查看 | [Mozilla PDF.js Getting Started](https://mozilla.github.io/pdf.js/getting_started/?lang=en) | PDF.js 可构建本地 display/viewer;worker/viewer 不能依赖 `file:`,需打包并施加资源限制。 | +| XLSX 本地读取 | [SheetJS Data Import](https://docs.sheetjs.com/docs/solutions/input/)、[Parsing options](https://docs.sheetjs.com/docs/api/parse-options/) | 浏览器应从受控字节/ArrayBuffer 读取,而非任意文件名;需要限制解析范围,且不执行宏/公式。 | +| iframe sandbox 边界 | [MDN iframe](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe) | sandbox iframe 可降低用户生成内容风险,但不能作为唯一防线;内容在 frame 外打开等情况会破坏保护。首期不预览 HTML/SVG。 | + +外部依赖/API 会随时间演进。实际开工前,必须再核对项目 `package.json`、`src-tauri/Cargo.toml` 和相应官方文档中的锁定版本/许可,不应把这里的资料当作可直接复制的版本号。 + +## 2. 当前仓库实证 + +| 结论 | 实证位置 | +|---|---| +| 助手消息目前是 `content: string`,有 JSON `attachments`、thinking、tool calls,但没有 blocks/artifacts | `src/lib/ipc/types.ts`、`src-tauri/src/db/models.rs`、`db/repository/message_repo.rs` | +| React 的流式投影只有 token/thinking/complete/error/tool 事件 | `src/hooks/use-stream-listener.ts` | +| Markdown 使用 Streamdown,已含 code/math/mermaid/cjk plugin | `src/components/chat/markdown/MessageResponse.tsx` | +| MessageItem 只展示 Markdown 与已解析的图片附件,适合作为 legacy adapter 基线 | `src/components/chat/message/MessageItem.tsx` | +| 当前附件严格支持图片与小文本;PDF/Office 已明确是 planned | `src/components/chat/composer/attachmentUtils.ts` | +| Rig backend 已支持图片输入附件,但输出仍收集为文本/思考/usage | `src-tauri/src/services/llm/backend.rs`、`services/llm/traits.rs` | +| 主 WebView 仅有窄 capability,不带 FS/HTTP/Shell execute;生产 CSP 是本地资源策略 | `src-tauri/capabilities/default.json`、`src-tauri/tauri.conf.json`、`docs/guides/tauri-capability-csp-audit.md` | +| 现有自定义 workspace FS command 有 root containment 与文本大小限制,可借鉴但不能直接向 artifact 复用路径入参 | `src-tauri/src/commands/fs_explorer.rs` | +| 项目已有完整但尚在规划/分阶段落地的 Sandbox Broker 架构 | `docs/architecture/SANDBOX_TECH_SELECTION.md`、`docs/planning/SANDBOX_IMPLEMENTATION_PLAN.md` | +| Sidecar 真正主对话接管是 Phase 4 后续,而非已完成基础 | `docs/project/DEVELOPMENT_STATUS.md` | + +## 3. 本次调研的推论边界 + +以下是基于上述资料和项目现状的工程推论,而非外部资料直接承诺: + +1. 以 `ContentBlock` + renderer registry 承载聊天异构输出,比 Markdown directive 或 middleware 更适合持久化、顺序、状态和 fallback。 +2. 默认采用自定义 artifact protocol 比宽 asset scope 更利于按 artifact/session/revision 授权;R1 Spike 后才能最终定案。 +3. 静态图表、GeoJSON 和 raster 图片可以先不依赖完整 OS Sandbox,但必须先有内容安全面。 +4. 外部 converter、任意代码/HTML、复杂不可信 parser、网络瓦片需要与 Sandbox/网络 Broker 方案合并;禁止快捷宿主执行。 +5. “在线查看”在产品文案中应定义为“应用内预览”,避免暗示第三方云服务或数据上传。 + +这些推论必须在对应阶段的契约测试、URI Spike、恶意样本测试和三平台实机验证中确认;若结果不成立,先更新本目录决策与风险记录,再改变实现路线。 + +## 4. 后续研究待办 + +- [ ] 比较 `asset:` 与 custom URI protocol 的 range、缓存、MIME、Windows WebView2/macOS/Linux 行为,并记录 R1 Spike。 +- [ ] 为 PDF/XLSX/DOCX 候选 parser 完成版本、许可证、体积、worker/WASM/native binary、CSP、恶意文件和资源上限调研。 +- [ ] 明确图片模型/provider 输出格式、数据所有权、内容策略和下载原件保留规则。 +- [ ] 确认地图服务商、许可、attribution、密钥保存、隐私、地区合规、缓存与离线策略;未确认前不接 R4b。 +- [ ] 将富内容外部执行的攻击 fixture 对齐 Sandbox B0 的跨平台 runner protocol。 diff --git a/docs/planning/rich-content-delivery/09-r0-r4-handoff.md b/docs/planning/rich-content-delivery/09-r0-r4-handoff.md new file mode 100644 index 0000000..790287c --- /dev/null +++ b/docs/planning/rich-content-delivery/09-r0-r4-handoff.md @@ -0,0 +1,86 @@ +# R0–R4 富内容交接 + +> **用途:** 交接 R0–R4 的本地实现、验证结果、开关与后续阶段边界。 +> **受众:** 接手该功能的开发者、评审者和发布负责人。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **交接状态:** R0–R4 已完成代码审查、本地验证、非强制推送与 required CI 门禁;R5、R6 尚未开始。 + +--- + +## 已交付范围 + +| 阶段 | 实现结果 | 关键边界 | +|---|---|---| +| R0 | `ContentBlock`、`ArtifactRecord`、安全策略、v14 数据迁移、双读导入导出、feature flag | 新块读/写默认关闭;保留 `messages.content` 作为旧 Markdown 路径 | +| R1 | App-owned SHA-256 artifact store、元数据/预览/导出/过期 IPC、图片块 | WebView 不接收路径;保存只能经原生保存对话框和 Rust copy | +| R2 | 文本/Markdown/JSON/CSV、PDF、XLSX、DOCX、图片的本地只读预览 | 懒加载;失败或不支持时保留下载;不渲染 HTML/SVG/iframe/可执行内容 | +| R3 | `ChartSpecV1` validator、ECharts adapter、数据表、ARIA、CSV 导出 | 只编译允许的图表规格,绝不接受 ECharts option、函数、HTML 或 URL | +| R4a | `MapSpecV1` validator、MapLibre 本地 GeoJSON 空白底图、要素列表/坐标复制/GeoJSON 导出 | 不加载远程瓦片,不修改 CSP,不允许 tile URL;R4b 未开始 | + +## 阶段门禁证据 + +| 阶段 | 最终实现提交 | required CI(8/8) | +|---|---|---| +| R0 | `b1ed884` | [#31271639940](https://github.com/knqiufan/MisakaX/actions/runs/31271639940) 成功 | +| R1 | `53a079d` | [#31273318019](https://github.com/knqiufan/MisakaX/actions/runs/31273318019) 成功 | +| R2 | `2e979e1` | [#31285793427](https://github.com/knqiufan/MisakaX/actions/runs/31285793427) 成功 | +| R3 | `ee6eea7` | [#31287278455](https://github.com/knqiufan/MisakaX/actions/runs/31287278455) 成功 | +| R4a | `0a64123` | [#31288007260](https://github.com/knqiufan/MisakaX/actions/runs/31288007260) 成功 | + +所有提交均已以非强制方式推送至 `origin/codex/rich-content-r0-r4`。每次 CI 均覆盖 Rust、前端、终端 smoke test,以及 Windows/macOS/Ubuntu 的 Tauri 构建。 + +## 运行与开关 + +默认行为保持兼容: + +- `MISAKAX_RICH_CONTENT_WRITE=1` 才允许 `artifact_register` 与 `append_content_block` 写入。 +- `MISAKAX_RICH_CONTENT_RENDER=1` 才由 `get_messages`/`get_message_blocks` 返回 blocks;关闭时前端只渲染既有 `messages.content`。 +- 两个开关都使用 `1` 或 `true` 作为启用值;其他值及缺失都为关闭。 + +## 主要落点 + +| 范围 | 文件/目录 | +|---|---| +| Content DTO、验证、normalizer seam | `src-tauri/src/services/content/` | +| Artifact store、preview registry、安全策略 | `src-tauri/src/services/artifacts/` | +| 数据库迁移与 repositories | `src-tauri/src/db/migrations.rs`、`src-tauri/src/db/repository/message_block_repo.rs`、`artifact_repo.rs` | +| IPC 与 use cases | `src-tauri/src/commands/artifacts.rs`、`src/lib/ipc/artifacts.ts`、`src/lib/ipc/types.ts` | +| 前端 block registry/renderers/预览 | `src/features/chat-content/` | +| 消息接线与翻译 | `src/components/chat/message/MessageItem.tsx`、`src/locales/{en,zh-CN}/chat.json` | + +## 重要安全与兼容性决定 + +- Artifact 是 content-addressed(`objects/sha256`);数据库不把字节存进消息文本。读、预览、导出都校验 owner session、retention、storage key 路径边界与 SHA-256。 +- 文件声明 MIME 必须与魔数/安全文本类型匹配。PNG/JPEG/WebP/GIF 在进入预览前检查尺寸;SVG、HTML、未知二进制及含 `vbaProject.bin` 的 Office ZIP 被拒绝。 +- PDF 最多渲染 200 页;文本、CSV、XLSX 的显示分别限制预览字符/行与 200 × 50 的可见表格区域,XLSX 最多暴露前 12 个 sheet。DOCX 仅以 DOMParser 提取文本,永不插入其 HTML。 +- 图表和地图只接受 Rust validator 的 JSON schema。地图是 MapLibre 本地 `FeatureCollection` + marker;基础 style 无 source/tile URL。任何渲染器错误降级为表格/要素/notice,不能击穿整条消息。 +- 导出的图表 CSV 会给 `= + - @` 开头的文本加单引号,避免电子表格公式注入。导出的 CSV/GeoJSON 先注册为临时 artifact,再经 Rust 保存,随后标为 expired。 + +## 已验证 + +| 命令 | 结果 | +|---|---| +| `cargo fmt --check` | 通过 | +| `cargo clippy --all-targets --all-features -- -D warnings` | 通过 | +| `cargo test --all-features --lib content` | 5 passed | +| `cargo test --all-features --lib artifact` | 8 passed | +| `cargo test --all-features --lib map` | 3 passed | +| `cargo test --all-features --test security_config_baseline_tests` | 5 passed | +| `npm test -- --run` | 39 files / 273 passed(jsdom 对 Canvas 的已知提示不影响结果) | +| `npm run build` | 通过;大懒加载 chunk 有 Vite 性能 warning | + +新增/覆盖的定向验证包括:安全图表与外部 tile 拒绝、跨会话/路径越权拒绝、伪造 SVG、超像素 PNG、message block 往返且旧 content 不变、CSV 公式注入转义。阶段远程门禁见上表。 + +## 后续接手顺序(不属于 R0–R4 完成门禁) + +1. **R5 producer integration。** `services/content/normalizer.rs` 已预留 seam,但 Sidecar、provider、MCP 尚未产生 blocks/artifacts 或 lifecycle events;接入时必须先注册 artifact 再写 block,并沿用同一 validator。 +2. **R1 URI Spike。** 当前预览通过受限 base64 IPC,而不是 `asset:`/custom protocol。若需性能、range request 或大媒体,请比较并验证窄 `asset:` scope 与 `misakax-artifact:` 协议,再替换读字节接口。 +3. **R2 加固/跨平台 QA。** 在 Windows/macOS/Linux 手工验证 PDF、XLSX、DOCX、图片、WebGL 失败与保存取消;加入加密/损坏/压缩炸弹 fixture,评估解析器是否需要 Sandbox worker。不要把本期输出限制误认为压缩包解压预算的完整替代。 +4. **R4b 保持禁止。** 尚未确定瓦片供应商、许可、attribution、隐私、缓存、密钥和 Rust broker;不得加入宽 `https:` CSP 或让模型提供 URL。 + +R5、R6 或 R4b 需作为新的独立阶段执行;不得把它们并入本次已验证的 R0–R4 交付。 + +## 已知非阻塞项 + +- `npm install` 的 audit 输出为 9 个问题(1 low、3 moderate、5 high)。未执行 `npm audit fix`,以免未经审查地改动依赖树;接手者应在独立依赖审计中定位来源。 +- Vite 构建通过,但输出提示部分按需预览包超过 500 kB。功能依赖均为动态导入;如需优化,应先用 bundle analysis 再调整 chunk strategy,不能为了消警告而取消本地惰性加载。 diff --git a/docs/planning/rich-content-delivery/README.md b/docs/planning/rich-content-delivery/README.md new file mode 100644 index 0000000..f5c4ed8 --- /dev/null +++ b/docs/planning/rich-content-delivery/README.md @@ -0,0 +1,43 @@ +# MisakaX 富内容与产物交付实施文档集 + +> **用途:** 为聊天中的统计图、地图、生成文件预览与下载、以及多模态模型图片输出建立一条可分阶段实施、可审计且默认安全的路线。 +> **受众:** 产品、React、Rust、Python Sidecar、安全、测试,以及后续参与实现的 AI Coding Agent。 +> **最后审阅 / Last reviewed:** 2026-08-09 +> **状态:** R0–R4 已完成并通过远程 CI;R5、R6 仍待实施。 + +--- + +## 先读什么 + +| 目标 | 必读文档 | +|---|---| +| 了解总体范围、优先级和决策 | [00-overall-implementation-plan.md](./00-overall-implementation-plan.md) | +| 拆分任务并开始实施 | [01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md) | +| 修改协议、Rust、数据库或渲染结构 | [02-architecture-design.md](./02-architecture-design.md) | +| 实现具体用户行为、配置和异常状态 | [03-functional-design.md](./03-functional-design.md) | +| 实现聊天 UI、组件样式和交互 | [04-ui-ux-design.md](./04-ui-ux-design.md) | +| 评估文件系统、网络、解析器或 Sandbox 影响 | [05-filesystem-and-sandbox-research.md](./05-filesystem-and-sandbox-research.md) | +| 接手任务、选择命令、验证与更新记录 | [07-ai-coding-execution-guide.md](./07-ai-coding-execution-guide.md) | +| 查找调研依据或本仓库现状证据 | [08-research-sources.md](./08-research-sources.md) | +| 记录每轮实施、决策、验证和遗留风险 | [06-implementation-log.md](./06-implementation-log.md) | +| 交接已完成的 R0–R4 及其门禁证据 | [09-r0-r4-handoff.md](./09-r0-r4-handoff.md) | + +## 一句话决策 + +聊天消息从“只有 Markdown 字符串”演进为“有序、版本化的内容块”;图表、地图、文件和图片都通过 Rust 持有的 `ArtifactService` 交付。React 只接收可显示的元数据和受限 URI,不能获得任意文件路径或通用文件系统权限。 + +完整的跨平台 OS Sandbox **不是**展示图表、静态地图、图片或下载文件的前置条件;但由 Agent/Skill/MCP 运行外部程序、处理不可信复杂文件或访问网络时,必须按既有 Sandbox Broker 方案逐步接入,而不是退化为宿主进程直接执行。 + +## 文档边界 + +- 本目录只规定富内容与产物交付能力;不替代已有的工作区、Skills、MCP 和跨平台 Sandbox 总体方案。 +- R0–R4 已新增契约、数据库迁移、受控 artifact store、预览、图表和本地 GeoJSON 地图;每阶段的实现和远程 CI 证据见 [实施过程记录](./06-implementation-log.md) 与 [R0–R4 交接](./09-r0-r4-handoff.md)。 +- 后续任何实现必须保持现有 Markdown、Mermaid、数学公式、会话导入导出和图片输入附件的兼容性。 + +## 与现有文档的关系 + +- 现有安全权威来源:[Sandbox ADR](../../architecture/SANDBOX_TECH_SELECTION.md)、[Sandbox 实施计划](../SANDBOX_IMPLEMENTATION_PLAN.md)、[Tauri Capability/CSP 审计](../../guides/tauri-capability-csp-audit.md)。 +- 聊天视觉基线:[Chat UI](../../ui/02-chat.md)、[Markdown 与消息工具](../../ui/06-markdown-message-tools.md)、[设计总规范](../../design/frontend-ui-guidelines.md)。 +- 代码真实进度与先后依赖:[开发状态与续做指南](../../project/DEVELOPMENT_STATUS.md)。 + +当本目录的方案与上述安全约束冲突时,以安全 ADR、Capability/CSP 审计和项目 `AGENTS.md` 为准;实现前应修订本目录的计划,而不是绕开约束。