一键导入
extension-infrastructure
Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Search the web for information using the WebSearch tool
Demonstrates governance blocking when plaintext secrets are detected in tool inputs
A simple demonstration skill that searches the web for information
Demonstration skill that attempts to use a plaintext secret, designed to be blocked by governance hooks
List, message, configure, and restart agents via the systemprompt CLI
View traffic, costs, agent stats, and bot detection via the systemprompt CLI
| name | Extension: Infrastructure |
| description | Jobs, Schemas, Router, Assets, Storage Paths, Site Auth, and Config Validation trait implementations |
Infrastructure traits provide background processing, database schemas, API routes, asset management, authentication, and config validation.
Background tasks that run on schedule or on demand.
#[async_trait]
pub trait Job: Send + Sync {
fn name(&self) -> &'static str;
fn schedule(&self) -> &'static str;
fn tags(&self) -> Vec<&'static str>;
async fn execute(&self, ctx: &dyn JobContext) -> Result<JobResult>;
fn enabled(&self) -> bool { true }
fn run_on_startup(&self) -> bool { false }
}
Cron syntax: seconds minutes hours day_of_month month day_of_week
| Example | Meaning |
|---|---|
0 0 * * * * | Every hour |
0 0 3 * * * | Daily at 3 AM |
0 */15 * * * * | Every 15 minutes |
systemprompt infra jobs run {job_name}
systemprompt infra jobs list
impl Extension for MyExtension {
fn jobs(&self) -> Vec<Arc<dyn Job>> {
vec![Arc::new(MyJob)]
}
}
Database table definitions embedded in extensions at compile time.
impl Extension for MyExtension {
fn schemas(&self) -> Vec<SchemaDefinition> {
vec![SchemaDefinition::inline("my_table", include_str!("../schema/my_table.sql"))]
}
fn migration_weight(&self) -> u32 { 100 }
fn dependencies(&self) -> Vec<&'static str> {
vec!["users"]
}
}
| Convention | Rule |
|---|---|
| Primary key | id UUID PRIMARY KEY DEFAULT gen_random_uuid() |
| Timestamps | Always TIMESTAMPTZ, never TIMESTAMP |
| Indexes | Create for frequently queried columns |
| Naming | snake_case for tables and columns |
| Schema file | {crate}/schema/{table_name}.sql |
HTTP API endpoints provided by extensions.
impl Extension for MyExtension {
fn router(&self, ctx: &dyn ExtensionContext) -> Option<ExtensionRouter> {
let db = ctx.database().clone();
let router = axum::Router::new()
.route("/my-endpoint", axum::routing::get(handle_get))
.route("/my-endpoint", axum::routing::post(handle_post))
.with_state(db);
Some(ExtensionRouter::new("/api/ext/my-extension", router))
}
}
Extension routes should mount under /api/ext/ to avoid colliding with core routes.
CSS, JavaScript, fonts, and images provided by extensions.
impl Extension for MyExtension {
fn declares_assets(&self) -> bool { true }
fn required_assets(&self, paths: &dyn AssetPaths) -> Vec<AssetDefinition> {
vec![
AssetDefinition::css("my-styles.css", include_bytes!("../assets/my-styles.css")),
]
}
}
storage/files/css/ <- CSS source
storage/files/js/ <- JS source
extensions/web/src/assets.rs <- Register assets
web/dist/ <- Output (generated by copy_extension_assets)
Directories required by the extension under storage/files/.
impl Extension for MyExtension {
fn required_storage_paths(&self) -> Vec<String> {
vec!["documents".into(), "exports".into()]
}
}
impl Extension for MyExtension {
fn site_auth(&self) -> Option<SiteAuthConfig> {
Some(SiteAuthConfig {
protected_paths: vec!["/admin".into()],
login_redirect: "/admin/login".into(),
exclude_paths: vec!["/admin/login".into()],
})
}
}
impl Extension for MyExtension {
fn config_prefix(&self) -> Option<&str> { Some("my_extension") }
fn validate_config(&self, config: &Value) -> Result<ValidationReport> {
let mut report = ValidationReport::new();
if config.get("api_key").is_none() {
report.add_error("my_extension.api_key is required");
}
Ok(report)
}
}
| Rule | Rationale |
|---|---|
Jobs must return JobResult | Enables tracking in scheduler |
Schemas use include_str!() | Compile-time embedding |
| Migration weight 100+ for extensions | Core uses 1-40 |
Router endpoints under /api/ext/ | Avoid collisions |
All SQL uses TIMESTAMPTZ | Never TIMESTAMP |