{
  "id": "runtime",
  "name": "Senpi Runtime",
  "description": "Senpi runtime plugin for OpenClaw. Orchestrates scanners, LLM-based trade decisions, and a DSL trailing stop-loss exit engine.",
  "version": "3.0.114",
  "commandAliases": [
    {
      "name": "senpi"
    }
  ],
  "activation": {
    "onStartup": true,
    "onCommands": [
      "senpi"
    ]
  },
  "contracts": {
    "tools": [
      "show_widget"
    ]
  },
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "stateDir": {
        "type": "string",
        "description": "Directory for plugin and strategy state (default: ~/.openclaw/senpi-state)"
      },
      "apiKey": {
        "type": "string",
        "description": "API key when mcpTransport is not provided by the gateway"
      },
      "logLevel": {
        "type": "string",
        "enum": [
          "debug",
          "info",
          "warn",
          "error"
        ],
        "description": "Minimum log level (default: info). Overrides the SENPI_LOG_LEVEL env var when set."
      },
      "toolApprovals": {
        "type": "string",
        "enum": [
          "off",
          "trades",
          "all"
        ],
        "description": "MCP tool approval gate mode override. \"trades\" requires interactive user approval before state-changing senpi MCP tools execute (create_position, strategy_withdraw_funds, ...); \"all\" gates every senpi MCP tool; \"off\" disables the gate. The gated tool set and the default mode (trades) ship in the checked-in src/approvals/tool-approvals-manifest.json — the reviewed, fleet-wide control surface. Precedence: SENPI_TOOL_APPROVALS env var > this setting > manifest default. Allow-always decisions persist per tool in <stateDir>/tool-approvals.json."
      },
      "autoUpdate": {
        "type": "object",
        "description": "Auto-update configuration. Enabled with auto-apply by default (opt-out). Omit this block entirely to use defaults.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Enable or disable auto-update polling (default: true)"
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto-apply",
              "notify-only"
            ],
            "description": "auto-apply installs updates automatically; notify-only sends a Telegram notification (default: auto-apply)"
          },
          "pollIntervalMinutes": {
            "type": "number",
            "description": "Minutes between version checks (default: 60, range: 1-1440)"
          },
          "startupDelaySeconds": {
            "type": "number",
            "description": "Seconds to wait after plugin start before the first version check (default: 30, range: 5-900)"
          },
          "allowPatch": {
            "type": "boolean",
            "description": "Allow automatic patch version updates (default: true)"
          },
          "allowMinor": {
            "type": "boolean",
            "description": "Allow automatic minor version updates (default: true)"
          },
          "failureBackoffMinutes": {
            "type": "number",
            "description": "Minutes to wait after a failed check before retrying (default: 2, range: 1-1440)"
          },
          "maxBackoffMinutes": {
            "type": "number",
            "description": "Maximum backoff ceiling in minutes (default: 30, range: 1-10080)"
          },
          "lastRestartTrigger": {
            "type": "string",
            "description": "Internal: timestamp written by the auto-updater to trigger gateway restart via config reload. Do not set manually."
          }
        }
      },
      "skillsManager": {
        "type": "object",
        "additionalProperties": false,
        "description": "Skills manager configuration. The managed skill set and each skill's source (repo/branch/path) come from the checked-in manifest src/skills-manager/skills-manifest.json — the single source of truth, shipped with the runtime. Checks the source repo for updates after each plugin auto-update tick and applies patch/minor updates automatically; major updates are gated by default (detected, surfaced via `senpi skills status`, applied via a manual `senpi skills update <name>` — no notification). To authorize automatic major upgrades, set a per-skill `maxMajor` ceiling in the manifest (or `overrides`): the tick then auto-applies majors up to and including that number; bumping it in a reviewed change is the fleet-wide lever for adopting a new skill major. Cadence is inherited from `autoUpdate.pollIntervalMinutes`; this block has no independent poll interval. Omit this block to manage the full manifest set with defaults.",
        "default": {
          "enabled": true
        },
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Enable or disable the skills manager (default: true)"
          },
          "skillsDir": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "minItems": 1
              }
            ],
            "description": "Directory (or directories) where managed skills are installed. Accepts a single string for one dir, or an array for a search path. With multiple, the first is the *primary* (writes go here on bootstrap/install); the rest are read-only mirrors scanned during version checks and discovery. Default: /data/.openclaw/skills. Env override: SENPI_SKILLS_DIR (comma-separated for multi-dir; use the JSON array form for paths containing commas)."
          },
          "skills": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Deprecated and ignored. The managed skill set is defined solely by the manifest (src/skills-manager/skills-manifest.json). This field is tolerated for backward compatibility with existing configs but no longer affects which skills are managed. Use `overrides` to retarget a skill's repo/branch/path, or `enabled: false` to disable the manager."
          },
          "overrides": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "repo": {
                  "type": "string"
                },
                "branch": {
                  "type": "string"
                },
                "commit": {
                  "type": "string",
                  "description": "Pin to a commit SHA, or 'latest' to track the branch tip."
                },
                "path": {
                  "type": "string"
                },
                "maxMajor": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Auto-update major-version ceiling: the tick auto-applies updates up to and including this major and gates anything above. Unset gates all majors (manual update required)."
                }
              }
            },
            "description": "Optional per-skill source overrides keyed by skill name, e.g. { \"senpi-strategy-ops\": { \"branch\": \"strategy-v2\" } }. Each entry may override repo, branch, and/or path. Branch precedence (highest first): per-skill env SENPI_SKILLS_BRANCH_<NAME> > this per-skill override > global env SENPI_SKILLS_BRANCH > manifest entry branch > manifest defaults.branch. So a per-skill override pins a skill even while the global env retargets the rest."
          }
        }
      },
      "widgets": {
        "type": "object",
        "description": "Per-widget-type on/off switch for the show_widget agent tool, keyed by widget_type (e.g. { \"fund_user_wallet\": false }). Absent or true enables a widget type; only an explicit false disables it. Adding a widget type does not change this schema. With every type disabled the tool is not registered.",
        "additionalProperties": {
          "type": "boolean"
        }
      },
      "api": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "host": {
            "type": "string",
            "default": "127.0.0.1",
            "description": "Bind interface inside the openclaw container. Default 127.0.0.1 (container loopback only). Set to 0.0.0.0 to enable Docker port mapping for Postman testing — see runtime-api.md."
          },
          "port": {
            "type": "integer",
            "minimum": 1,
            "maximum": 65535,
            "default": 8787
          },
          "maxItemsPerSignalsRequest": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "default": 10,
            "description": "Maximum number of items in a single POST /signals body. Conservative default — operators raise it consciously when broadcasting to many wallets at once."
          }
        }
      }
    }
  },
  "uiHints": {}
}
