wiki: Configuration

hermes committed 2026-10-21 10:57:01 +00:00
1 parent 36ac73c65b
commit c48a2eb9e1
1 file changed
+163
+163
@@ -0,0 +1,163 @@
# Configuration
`Config` is a Schemastery schema plus a same-named interface. It is validated when the plugin loads; invalid config fails the load with an actionable error. A config edit hot-replaces the plugin.
## Full schema
```ts
import Schema from '@deepseek-ai/schemastery'
export interface Config {
accessToken: string
userAccessToken?: string
groupId: number
apiVersion: string
language: 'ru' | 'en' | 'uk'
rateLimit: { rps: number; burst: number; maxConcurrent: number }
retry: { maxAttempts: number; baseDelayMs: number; maxDelayMs: number; retryOn: number[] }
captcha: { policy: 'fail' | 'ask'; solverTool?: string }
longpoll: { enabled: boolean; mode: 0 | 1 | 2; timeoutSec: number; batchMs: number }
callback: { enabled: boolean; serverUrl?: string; confirmToken?: string; secret?: string }
moderation: { enabled: boolean; autoApprove: boolean; warnThreshold: number; exemptUserIds: number[] }
safety: { requireConfirmForDestructive: boolean; dryRunDefault: boolean; rawApiEnabled: boolean }
notifications: { onMessage: boolean; onComment: boolean; onJoin: boolean; onLeave: boolean }
ui: { settingsTab: boolean; moderationQueue: boolean }
}
```
## Field reference
### `accessToken` (required)
The **community** token. Never logged, never placed in tool arguments, never returned by any tool. Read once in `apply`, held in a closure, redacted in the audit log as `<redacted>`.
### `userAccessToken` (optional)
The admin's **user** token. Unlocks `vk_members_list`, `vk_stats_get`, and the complete `vk_ban_list`. Without it those tools return `VK_SCOPE_MISSING` naming the exact scope.
### `groupId`
The community id. Accepts either sign; normalized internally to a negative number for `owner_id` purposes.
### `apiVersion`
Default `'5.199'`. Sent on every request. Do not leave it unset — VK's behaviour without `v` is unpredictable.
### `language`
`'ru' | 'en' | 'uk'`. Passed as `lang` on requests that accept it and used for VK-generated error text.
### `rateLimit`
| Field | Default | Meaning |
|---|---|---|
| `rps` | 3 | sustained requests per second for the community token |
| `burst` | 5 | token-bucket depth |
| `maxConcurrent` | 2 | in-flight request cap |
Raise `rps` only if you use a user token (limit ~20/s). Exceeding it yields `error 6`.
### `retry`
| Field | Default | Meaning |
|---|---|---|
| `maxAttempts` | 4 | total attempts including the first |
| `baseDelayMs` | 400 | first backoff delay |
| `maxDelayMs` | 8000 | backoff ceiling |
| `retryOn` | `[1, 6, 9, 10]` | VK error codes treated as transient |
Everything not in `retryOn` fails fast. `5` (auth), `15` (access), `100` (bad param) must never be retried.
### `captcha`
`policy: 'fail'` (default) — return `VK_CAPTCHA_REQUIRED` with the `captcha_sid` and stop. `policy: 'ask'` — the pre-execute gate returns `ask` so a human can solve it and the call resumes with `captcha_key`.
`solverTool` names an external tool that can solve the captcha; it is **not** built in. Automated captcha solving is out of scope (see Non-Goals).
### `longpoll`
| Field | Default | Meaning |
|---|---|---|
| `enabled` | false | start the background job on load |
| `mode` | 2 | 0 = no typing/online, 1 = messages only, 2 = messages + typing |
| `timeoutSec` | 25 | `wait` parameter |
| `batchMs` | 1500 | window over which events are coalesced into one agent message |
### `callback`
Off by default — needs a public HTTPS endpoint. When enabled, `serverUrl`, `confirmToken` and `secret` are required (validated by the schema).
### `moderation`
| Field | Default | Meaning |
|---|---|---|
| `enabled` | false | run the rule engine |
| `autoApprove` | false | auto-approve join requests (dangerous; opt-in only) |
| `warnThreshold` | 3 | warnings before an automatic ban |
| `exemptUserIds` | `[]` | users the engine never touches |
### `safety`
| Field | Default | Meaning |
|---|---|---|
| `requireConfirmForDestructive` | true | destructive tools return `ask` from pre-execute |
| `dryRunDefault` | true | `vk_community_update` defaults to `dryRun: true` |
| `rawApiEnabled` | false | enables `vk_api_raw` |
### `notifications`
Per-event-type switches for the LongPoll → agent bridge. `onJoin`/`onLeave` are off by default because a busy community generates a lot of noise.
### `ui`
`settingsTab` adds a settings panel; `moderationQueue` adds the moderation queue view. Both require the client half of the plugin to be installed in a Web profile.
## Example: production profile
```yaml
- insert:
- id: vk-group
name: dsh-vk-group
config:
groupId: -123456789
accessToken: !!js process.env.VK_COMMUNITY_TOKEN
userAccessToken: !!js process.env.VK_USER_TOKEN
apiVersion: '5.199'
language: ru
rateLimit: { rps: 3, burst: 5, maxConcurrent: 2 }
longpoll: { enabled: true, mode: 2, timeoutSec: 25, batchMs: 1500 }
moderation: { enabled: true, autoApprove: false, warnThreshold: 3, exemptUserIds: [1] }
safety: { requireConfirmForDestructive: true, dryRunDefault: true, rawApiEnabled: false }
notifications: { onMessage: true, onComment: true, onJoin: false, onLeave: false }
```
## Example: read-only audit profile
```yaml
- insert:
- id: vk-group
name: dsh-vk-group
config:
groupId: -123456789
accessToken: !!js process.env.VK_COMMUNITY_TOKEN
longpoll: { enabled: false }
safety: { requireConfirmForDestructive: true, dryRunDefault: true, rawApiEnabled: false }
ui: { settingsTab: false, moderationQueue: false }
```
## Secrets
Tokens come from the environment, never from the patch file. Use `!!js process.env.X` — DSH evaluates the expression against the injected context after the row's dependencies are ready.
Never commit a `.env` with real tokens. The audit log redacts tokens as `<redacted>`; if you add a new log line, redact there too.
## Validation failures
| Symptom | Cause |
|---|---|
| `accessToken: required` | missing token |
| `groupId: expected number` | id passed as a string |
| `callback.serverUrl: required` | `callback.enabled: true` without a URL |
| `rateLimit.rps: must be > 0` | zero or negative |
Failures are loud by design — the plugin refuses to load rather than degrading silently.