dsh-plugin-discourse 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AkarinLiu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,143 @@
1
- # Temporary Holding Version
1
+ # dsh-plugin-discourse
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Discourse administration and agent tools for the [DeepSeek Harness](https://github.com/deepseek-ai).
4
+
5
+ One Host plugin registers 16 model-facing tools over the Discourse REST API: an agent can search a
6
+ forum, read topics and profiles, publish posts, and carry out the moderator and administrator work a
7
+ staff account would do in the web UI.
8
+
9
+ ```
10
+ User → DSH agent → discourse_* tools → Discourse REST API → forum
11
+ ```
12
+
13
+ ## Tools
14
+
15
+ | Tool | Group | What it does | Key needed |
16
+ |---|---|---|---|
17
+ | `discourse_search` | read | Search topics, posts, and users | no |
18
+ | `discourse_topics` | read | List a feed (`latest`/`new`/`unread`/`top`) or one category | no |
19
+ | `discourse_topic` | read | Read a topic and a slice of its posts | no |
20
+ | `discourse_categories` | read | List categories and subcategories with ids | no |
21
+ | `discourse_user` | read | Read one profile with roles, trust level, and activity counts | no |
22
+ | `discourse_create_topic` | author | Create a topic with category and tags | yes |
23
+ | `discourse_reply` | author | Reply to a topic, optionally to a specific post | yes |
24
+ | `discourse_update_post` | author | Replace a post body | yes |
25
+ | `discourse_flag_post` | author | Flag a post as spam, inappropriate, or off-topic | yes |
26
+ | `discourse_review_queue` | moderate | List flagged items awaiting a decision | moderator |
27
+ | `discourse_delete_post` | moderate | Delete or permanently destroy a post | moderator |
28
+ | `discourse_restore_post` | moderate | Restore a deleted post | moderator |
29
+ | `discourse_admin_users` | admin | Search the user directory by status and order | admin |
30
+ | `discourse_moderate_user` | admin | Suspend, silence, lift a sanction, or activate an account | admin |
31
+ | `discourse_site_settings` | admin | Read settings, or change one by name | admin |
32
+ | `discourse_admin_stats` | admin | Read a dashboard report as a time series | admin |
33
+
34
+ Every listing is bounded (12 items by default, 50 maximum) and every post body is clipped, so a
35
+ thread search never floods the model context. Results keep ids, so a follow-up call reads the detail.
36
+
37
+ ## Install
38
+
39
+ The bundle is a profile plugin: it is installed into one DSH profile and selected in that profile's
40
+ bundle list.
41
+
42
+ **From the Web UI** — open *Settings → Plugins → Install bundle* and give it the package directory
43
+ (for a clone) or a package spec such as `github:AkarinLiu/dsh-plugin-discourse`. DSH installs the
44
+ package, adds it to the profile's bundle list, and activates it.
45
+
46
+ **From the CLI** — the launcher passes everything after `plugin` to pnpm:
47
+
48
+ ```bash
49
+ gh repo clone AkarinLiu/dsh-plugin-discourse
50
+ dsh plugin --profile desktop add ./dsh-plugin-discourse
51
+ ```
52
+
53
+ That installs the package; select `dsh-plugin-discourse` once in the Plugins page (or through the
54
+ `plugin_manager` tool) so the profile records it as a bundle.
55
+
56
+ To remove it, uninstall the bundle from the Plugins page, which drops the dependency and the bundle
57
+ entry together.
58
+
59
+ > The plugin is Host-only: no build step, no dependencies, no client assets.
60
+
61
+ ## Configure
62
+
63
+ The bundle ships its defaults in `cordis.patch.yml`, which DSH applies as the bundle layer. To point
64
+ it at your forum, add an override to your **profile's** `cordis.patch.yml` (`$DSH_HOME/profiles/<name>/cordis.patch.yml`):
65
+
66
+ ```yaml
67
+ - id: discourse
68
+ name: dsh-plugin-discourse
69
+ config:
70
+ baseUrl: https://forum.example.com
71
+ apiKey: ''
72
+ apiUsername: ''
73
+ readOnly: true
74
+ timeoutMs: 20000
75
+ maxItems: 12
76
+ ```
77
+
78
+ A loader override replaces the row's `config` wholesale, so restate every key you want to keep.
79
+
80
+ | Key | Default | Meaning |
81
+ |---|---|---|
82
+ | `baseUrl` | `https://meta.discourse.org` | Forum origin. Point this at your own forum. |
83
+ | `apiKey` | `''` | Discourse API key. Empty means anonymous, read-only access. |
84
+ | `apiUsername` | `''` → `system` | Username the key acts as. |
85
+ | `readOnly` | `false` | Blocks every mutating tool when `true`. |
86
+ | `timeoutMs` | `20000` | Per-request deadline, 1000–120000. |
87
+ | `maxItems` | `12` | Default listing size, 1–50. |
88
+
89
+ Anonymous reads work out of the box against the default forum, so you can try `discourse_topics`
90
+ before configuring anything.
91
+
92
+ ### Credentials
93
+
94
+ Generate a key in Discourse under *Admin → API → API keys*. Two shapes work:
95
+
96
+ - **Global key with an admin user** — full tool coverage, including `discourse_admin_*`.
97
+ - **Granular key** — grant only the scopes you want (`topics:write`, `posts:write`, `users:moderate`,
98
+ and similar). Any tool whose scope is missing fails with the forum's own 403 message.
99
+
100
+ Rather than storing the secret in YAML, the plugin also reads it from the environment:
101
+
102
+ ```bash
103
+ export DISCOURSE_API_KEY="..."
104
+ export DISCOURSE_API_USERNAME="staff-bot"
105
+ ```
106
+
107
+ Row config wins over the environment when both are present.
108
+
109
+ ## Safety
110
+
111
+ - `readOnly: true` is enforced inside the plugin, before any mutating request is built.
112
+ - `discourse_moderate_user` and the site-settings tools require an admin-scoped key; a key without
113
+ those scopes receives the forum's 403 response, and the tool reports it instead of retrying.
114
+ - Failures carry the HTTP status and Discourse's own error text, so a wrong id or a missing scope is
115
+ visible in the transcript.
116
+ - Writes should be exercised with a staging forum first — `discourse_delete_post` with
117
+ `permanent: true` is irreversible.
118
+
119
+ ## Development
120
+
121
+ The package is plain ESM with no runtime dependencies; `index.js` is the whole plugin.
122
+
123
+ ```bash
124
+ node --check index.js # syntax
125
+ node scripts/smoke.mjs # register every tool and validate definitions offline
126
+ node scripts/smoke.mjs --live # additionally call read-only tools against the configured forum
127
+ ```
128
+
129
+ `scripts/smoke.mjs` drives `apply()` with a stub context, so it exercises the real registration path
130
+ without starting a Harness.
131
+
132
+ ## 中文说明
133
+
134
+ - 这是一个 **Host 插件**,向 DSH 智能体提供 16 个 Discourse 工具(读取 / 发帖 / 版主 / 管理员)。
135
+ - 安装:在 DSH Web UI 的 *设置 → 插件 → 安装 bundle* 中选择本仓库目录,或填入 `github:AkarinLiu/dsh-plugin-discourse`。
136
+ - 配置:在 profile 的 `cordis.patch.yml` 中加一条 `id: discourse` 的覆盖,把 `baseUrl` 改成你的论坛并填入 `apiKey`(覆盖会整体替换 `config`,请把其它键一并写全)。
137
+ - 不需要 API Key 即可试用只读工具(默认指向 `https://meta.discourse.org`)。
138
+ - 密钥建议通过环境变量 `DISCOURSE_API_KEY` / `DISCOURSE_API_USERNAME` 提供,避免写进配置文件。
139
+ - 不需要写入权限时把 `readOnly` 设为 `true`,所有写操作会被插件直接拒绝。
140
+
141
+ ## License
142
+
143
+ MIT © 2026 AkarinLiu. See [LICENSE](LICENSE).
@@ -0,0 +1,13 @@
1
+ # Inserts the Discourse tool bundle into the current DSH profile.
2
+ # Change `baseUrl` to your forum and point `apiKey` at an admin-scoped key
3
+ # before enabling writes.
4
+ - insert:
5
+ - id: discourse
6
+ name: dsh-plugin-discourse
7
+ config:
8
+ baseUrl: https://meta.discourse.org
9
+ apiKey: ''
10
+ apiUsername: ''
11
+ readOnly: false
12
+ timeoutMs: 20000
13
+ maxItems: 12
package/icon.svg ADDED
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="Discourse forum tools">
2
+ <defs>
3
+ <linearGradient id="discourse-bg" x1="0" y1="0" x2="1" y2="1">
4
+ <stop offset="0" stop-color="#3b5bdb"/>
5
+ <stop offset="1" stop-color="#0ea5a3"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect width="64" height="64" rx="15" fill="url(#discourse-bg)"/>
9
+ <path d="M17 15h30a6 6 0 0 1 6 6v16a6 6 0 0 1-6 6H31l-10 8v-8h-4a6 6 0 0 1-6-6V21a6 6 0 0 1 6-6z" fill="#ffffff" opacity="0.96"/>
10
+ <circle cx="23" cy="29" r="2.6" fill="#3b5bdb"/>
11
+ <circle cx="32" cy="29" r="2.6" fill="#3b5bdb"/>
12
+ <circle cx="41" cy="29" r="2.6" fill="#3b5bdb"/>
13
+ <path d="M46 38l7 3v6.5c0 4.2-3 7.6-7 8.5-4-0.9-7-4.3-7-8.5V41l7-3z" fill="#ffffff" opacity="0.96"/>
14
+ <path d="M43.4 46.4l2.1 2.1 4-4.4" fill="none" stroke="#0ea5a3" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
15
+ </svg>