dsh-telegram-connector 0.14.1 → 0.15.1
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/CHANGELOG.md +19 -0
- package/COMPATIBILITY.md +1 -0
- package/README.md +22 -5
- package/lib/client.js +176 -0
- package/package.json +16 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.1
|
|
4
|
+
|
|
5
|
+
- Release-check fix: the `0.15.0` tag was cut without its COMPATIBILITY row and
|
|
6
|
+
was never published; this is the published release of the configuration page
|
|
7
|
+
described below.
|
|
8
|
+
|
|
9
|
+
## 0.15.0
|
|
10
|
+
|
|
11
|
+
- **The connector has a configuration page.** On DSH `0.2.1-rc.5` or newer, the
|
|
12
|
+
Plugins page shows **Configure** on the `dsh-telegram-connector` row: bot
|
|
13
|
+
token, allowed user ids and admin user id, saved through the page's own form.
|
|
14
|
+
No `.env` edit or restart is needed; the connector recomposes and starts.
|
|
15
|
+
- **Standalone is a first-class mode.** The setup is optional: the connector
|
|
16
|
+
does not assume the setup supervisor or updater. The setup-specific commands
|
|
17
|
+
report the missing sidecar instead of failing; workspaces, sessions, topics,
|
|
18
|
+
plugins and model calls work on any DSH runtime.
|
|
19
|
+
- The browser half is plain JavaScript in the client-module format, copied to
|
|
20
|
+
`lib/client.js` by the build; the host half is unchanged.
|
|
21
|
+
|
|
3
22
|
## 0.14.1
|
|
4
23
|
|
|
5
24
|
- **Component actions no longer restart the runtime.** The setup's
|
package/COMPATIBILITY.md
CHANGED
|
@@ -6,6 +6,7 @@ every release.
|
|
|
6
6
|
|
|
7
7
|
| Connector | DSH | Status | Notes |
|
|
8
8
|
|---|---|---|---|
|
|
9
|
+
| 0.15.1 | `0.2.1-rc.5` | needs UAT | config page (Plugins → Configure) for bot token, allowed ids and admin id; standalone without the setup updater |
|
|
9
10
|
| 0.14.1 | `0.2.1-rc.5` | needs UAT | component actions no longer restart the runtime; the tools load on the next start |
|
|
10
11
|
| 0.14.0 | `0.2.1-rc.5` | needs UAT | one command surface: `/menu` card, `/plugins` subcommands, `/components`; aliases and `/man` removed |
|
|
11
12
|
| 0.13.1 | `0.2.1-rc.5` | needs UAT | `/system status` probes the advertised web address, so a LAN-only bind no longer reports loopback as unreachable |
|
package/README.md
CHANGED
|
@@ -141,11 +141,11 @@ Telegram:
|
|
|
141
141
|
```sh
|
|
142
142
|
git clone https://github.com/vladtsvirko/dsh-tg-docker-setup
|
|
143
143
|
cd dsh-tg-docker-setup
|
|
144
|
-
./
|
|
144
|
+
./setup.sh # asks for port, bind address, provider, key,
|
|
145
145
|
# bot token, allowed ids, admin id, git author
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
`./
|
|
148
|
+
`./setup.sh --check` prints the whole plan and changes nothing. The setup
|
|
149
149
|
pins a recommended connector tag in its `plugins.json`; the connector is
|
|
150
150
|
versioned on its own and can move to a newer compatible version from the bot without
|
|
151
151
|
a setup release. See [`docs/STANDALONE.md`](docs/STANDALONE.md) for the same
|
|
@@ -154,8 +154,7 @@ install without the setup.
|
|
|
154
154
|
The connector is published to npm as an exact version:
|
|
155
155
|
|
|
156
156
|
```sh
|
|
157
|
-
dsh plugin --profile web add dsh-telegram-connector@0.
|
|
158
|
-
export DSH_TELEGRAM_BOT_TOKEN='123456:ABC…'
|
|
157
|
+
dsh plugin --profile web add dsh-telegram-connector@0.15.1
|
|
159
158
|
```
|
|
160
159
|
|
|
161
160
|
The registry tarball already contains the built `lib/`, so there is no
|
|
@@ -163,6 +162,21 @@ The registry tarball already contains the built `lib/`, so there is no
|
|
|
163
162
|
the plugin. The setup's `plugins.json` uses the same spec and keeps the GitHub
|
|
164
163
|
tag as a fallback when the registry is unreachable.
|
|
165
164
|
|
|
165
|
+
### Configure in the UI
|
|
166
|
+
|
|
167
|
+
On DSH `0.2.1-rc.5` or newer, open **Plugins** → **dsh-telegram-connector** and
|
|
168
|
+
press **Configure** on the `dsh-telegram-connector` row. The page has three
|
|
169
|
+
fields — **bot token**, **allowed user ids** and **admin user id** — and
|
|
170
|
+
**Save** writes the row's config into the profile's user layer. No `.env` edit
|
|
171
|
+
or restart is needed; the connector recomposes and starts polling.
|
|
172
|
+
|
|
173
|
+
That is the standalone path: the setup is not required, and the connector does
|
|
174
|
+
not assume the setup's supervisor or updater. Commands that need them
|
|
175
|
+
(`/system update setup`, `/components`, `/firewall allow`, restart/rollback)
|
|
176
|
+
report that the sidecar is unavailable instead of failing. Everything else —
|
|
177
|
+
workspaces, sessions, topics, plugins and model calls — works on any DSH
|
|
178
|
+
runtime.
|
|
179
|
+
|
|
166
180
|
Installing from the source repository is still possible:
|
|
167
181
|
|
|
168
182
|
```sh
|
|
@@ -170,7 +184,7 @@ cat >> "$DSH_HOME/profiles/web/pnpm-workspace.yaml" <<'YAML'
|
|
|
170
184
|
allowBuilds:
|
|
171
185
|
dsh-telegram-connector@https://github.com/vladtsvirko/dsh-telegram-connector.git: true
|
|
172
186
|
YAML
|
|
173
|
-
dsh plugin --profile web add github:vladtsvirko/dsh-telegram-connector#v0.
|
|
187
|
+
dsh plugin --profile web add github:vladtsvirko/dsh-telegram-connector#v0.15.1
|
|
174
188
|
```
|
|
175
189
|
|
|
176
190
|
That path runs the package's `prepare` build; pnpm ≥ 10 refuses it until the
|
|
@@ -180,6 +194,9 @@ The package is a plugin bundle: `cordis.patch.yml` mounts one row.
|
|
|
180
194
|
|
|
181
195
|
## Configuration
|
|
182
196
|
|
|
197
|
+
The row config from the UI is the first source. The environment is the
|
|
198
|
+
fallback (the setup writes it; a standalone profile can export it instead):
|
|
199
|
+
|
|
183
200
|
Environment:
|
|
184
201
|
|
|
185
202
|
| Variable | Meaning |
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser half: the configuration page for the `dsh-telegram-connector` row.
|
|
3
|
+
*
|
|
4
|
+
* DSH's Plugins page declares the `plugins.row.config` slot; this module
|
|
5
|
+
* registers the row's page with the three answers a fresh standalone install
|
|
6
|
+
* needs. The host half already reads the same keys from its Config schema; the
|
|
7
|
+
* patch keeps the environment as the fallback, and a value saved here is the
|
|
8
|
+
* profile's user layer, which wins over it.
|
|
9
|
+
*/
|
|
10
|
+
window.__ModuleLoader__.load({
|
|
11
|
+
id: 'dsh-telegram-connector',
|
|
12
|
+
factory: (require) => {
|
|
13
|
+
var module = { exports: {} }
|
|
14
|
+
var exports = module.exports
|
|
15
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' })
|
|
16
|
+
|
|
17
|
+
const React = require('react')
|
|
18
|
+
const h = React.createElement
|
|
19
|
+
|
|
20
|
+
const KEY = 'dsh-telegram-connector#dsh-telegram-connector'
|
|
21
|
+
const inputStyle = {
|
|
22
|
+
boxSizing: 'border-box',
|
|
23
|
+
width: '100%',
|
|
24
|
+
padding: '6px 8px',
|
|
25
|
+
borderRadius: 6,
|
|
26
|
+
border: '1px solid var(--dsh-border, #d0d5dd)',
|
|
27
|
+
background: 'var(--dsh-surface, #fff)',
|
|
28
|
+
color: 'inherit',
|
|
29
|
+
font: 'inherit',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function field(label, hint, input) {
|
|
33
|
+
return h(
|
|
34
|
+
'label',
|
|
35
|
+
{ style: { display: 'flex', flexDirection: 'column', gap: 4, marginBottom: 14 } },
|
|
36
|
+
h('span', { style: { fontWeight: 600 } }, label),
|
|
37
|
+
hint === undefined ? null : h('span', { style: { opacity: 0.7, fontSize: 12 } }, hint),
|
|
38
|
+
input,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function parseIds(text) {
|
|
43
|
+
return text
|
|
44
|
+
.split(/[\s,]+/)
|
|
45
|
+
.map((part) => part.trim())
|
|
46
|
+
.filter((part) => part.length > 0)
|
|
47
|
+
.map((part) => Number(part))
|
|
48
|
+
.filter((id) => Number.isFinite(id) && id > 0)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function TelegramConfigForm({ form }) {
|
|
52
|
+
if (form === undefined) {
|
|
53
|
+
return h('p', null, 'This plugin does not expose its configuration in this build.')
|
|
54
|
+
}
|
|
55
|
+
const state = form.state
|
|
56
|
+
if (state.status === 'unavailable') {
|
|
57
|
+
return h('p', null, 'This plugin is not loaded, so it cannot be configured right now.')
|
|
58
|
+
}
|
|
59
|
+
if (state.status === 'loading') {
|
|
60
|
+
return h('p', null, 'Loading the current values…')
|
|
61
|
+
}
|
|
62
|
+
const value = state.value ?? {}
|
|
63
|
+
const [botToken, setBotToken] = React.useState(String(value.botToken ?? ''))
|
|
64
|
+
const [allowed, setAllowed] = React.useState(Array.isArray(value.allowedUserIds) ? value.allowedUserIds.join(', ') : '')
|
|
65
|
+
const [admin, setAdmin] = React.useState(value.adminUserId === undefined ? '' : String(value.adminUserId))
|
|
66
|
+
const [saving, setSaving] = React.useState(false)
|
|
67
|
+
const [message, setMessage] = React.useState('')
|
|
68
|
+
|
|
69
|
+
React.useEffect(() => {
|
|
70
|
+
const next = state.value ?? {}
|
|
71
|
+
setBotToken(String(next.botToken ?? ''))
|
|
72
|
+
setAllowed(Array.isArray(next.allowedUserIds) ? next.allowedUserIds.join(', ') : '')
|
|
73
|
+
setAdmin(next.adminUserId === undefined ? '' : String(next.adminUserId))
|
|
74
|
+
}, [state.revision])
|
|
75
|
+
|
|
76
|
+
const disabled = !state.writable || saving
|
|
77
|
+
const save = async () => {
|
|
78
|
+
const ids = parseIds(allowed)
|
|
79
|
+
const adminId = admin.trim().length === 0 ? undefined : Number(admin.trim())
|
|
80
|
+
if (adminId !== undefined && (!Number.isFinite(adminId) || adminId <= 0)) {
|
|
81
|
+
setMessage('The admin user id must be a number, or empty to use the first allowed id.')
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
setSaving(true)
|
|
85
|
+
setMessage('')
|
|
86
|
+
try {
|
|
87
|
+
const ops = [
|
|
88
|
+
{ op: 'set', path: ['botToken'], value: botToken.trim() },
|
|
89
|
+
{ op: 'set', path: ['allowedUserIds'], value: ids },
|
|
90
|
+
adminId === undefined
|
|
91
|
+
? { op: 'unset', path: ['adminUserId'] }
|
|
92
|
+
: { op: 'set', path: ['adminUserId'], value: adminId },
|
|
93
|
+
]
|
|
94
|
+
const ok = await form.mutate(ops, state.revision)
|
|
95
|
+
setMessage(ok ? 'Saved. The connector reconnects with these values.' : 'The deployment did not accept these values; they were left for you to correct.')
|
|
96
|
+
} catch (error) {
|
|
97
|
+
setMessage(`Save failed: ${String(error)}`)
|
|
98
|
+
} finally {
|
|
99
|
+
setSaving(false)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return h(
|
|
104
|
+
'div',
|
|
105
|
+
null,
|
|
106
|
+
h('p', null, 'Connect the bot to Telegram. The token comes from @BotFather; user ids are numeric and come from @userinfobot.'),
|
|
107
|
+
field(
|
|
108
|
+
'Bot token',
|
|
109
|
+
'For example 123456789:AA… . Keep it out of screenshots and commits.',
|
|
110
|
+
h('input', {
|
|
111
|
+
type: 'password',
|
|
112
|
+
value: botToken,
|
|
113
|
+
disabled,
|
|
114
|
+
placeholder: 'the token from @BotFather',
|
|
115
|
+
style: inputStyle,
|
|
116
|
+
onChange: (event) => setBotToken(event.target.value),
|
|
117
|
+
}),
|
|
118
|
+
),
|
|
119
|
+
field(
|
|
120
|
+
'Allowed user ids',
|
|
121
|
+
'Comma- or space-separated numeric ids. Everyone in this list can talk to the agent and use the sessions.',
|
|
122
|
+
h('input', {
|
|
123
|
+
type: 'text',
|
|
124
|
+
value: allowed,
|
|
125
|
+
disabled,
|
|
126
|
+
placeholder: '142283532, 777000111',
|
|
127
|
+
style: inputStyle,
|
|
128
|
+
onChange: (event) => setAllowed(event.target.value),
|
|
129
|
+
}),
|
|
130
|
+
),
|
|
131
|
+
field(
|
|
132
|
+
'Admin user id',
|
|
133
|
+
'Optional. One allowed id that may update, restart, roll back and manage plugins; empty uses the first allowed id.',
|
|
134
|
+
h('input', {
|
|
135
|
+
type: 'text',
|
|
136
|
+
value: admin,
|
|
137
|
+
disabled,
|
|
138
|
+
placeholder: 'optional',
|
|
139
|
+
style: inputStyle,
|
|
140
|
+
onChange: (event) => setAdmin(event.target.value),
|
|
141
|
+
}),
|
|
142
|
+
),
|
|
143
|
+
h(
|
|
144
|
+
'div',
|
|
145
|
+
{ style: { display: 'flex', alignItems: 'center', gap: 10 } },
|
|
146
|
+
h(
|
|
147
|
+
'button',
|
|
148
|
+
{
|
|
149
|
+
type: 'button',
|
|
150
|
+
disabled,
|
|
151
|
+
onClick: save,
|
|
152
|
+
style: { padding: '6px 14px', borderRadius: 6, cursor: disabled ? 'default' : 'pointer' },
|
|
153
|
+
},
|
|
154
|
+
saving ? 'Saving…' : 'Save',
|
|
155
|
+
),
|
|
156
|
+
message.length === 0 ? null : h('span', { style: { fontSize: 13 } }, message),
|
|
157
|
+
),
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const inject = ['slots']
|
|
162
|
+
function apply(ctx) {
|
|
163
|
+
ctx.slots.inject('plugins.row.config', () =>
|
|
164
|
+
ctx.slots.register(
|
|
165
|
+
{ name: 'plugins.row.config', key: KEY },
|
|
166
|
+
({ view, form }) => (view === 'summary' ? null : h(TelegramConfigForm, { form })),
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
exports.NS = 'dsh-telegram-connector'
|
|
172
|
+
exports.apply = apply
|
|
173
|
+
exports.inject = inject
|
|
174
|
+
return module.exports
|
|
175
|
+
},
|
|
176
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-telegram-connector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Telegram control plane for DeepSeek Harness \u2014 one group per workspace, one forum topic per session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"node": ">=22"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
|
-
"build": "tsc -p tsconfig.json",
|
|
29
|
+
"build": "tsc -p tsconfig.json && node scripts/copy-client.mjs",
|
|
30
30
|
"prepare": "npm run build",
|
|
31
31
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
32
32
|
"test": "vitest run",
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
"dsh": {
|
|
38
38
|
"bundle": {
|
|
39
39
|
"patch": "./cordis.patch.yml"
|
|
40
|
+
},
|
|
41
|
+
"client": {
|
|
42
|
+
"inject": [
|
|
43
|
+
"@deepseek-ai/dsh-client-ui-slots"
|
|
44
|
+
],
|
|
45
|
+
"platform": "web"
|
|
40
46
|
}
|
|
41
47
|
},
|
|
42
48
|
"peerDependencies": {
|
|
@@ -67,5 +73,13 @@
|
|
|
67
73
|
],
|
|
68
74
|
"publishConfig": {
|
|
69
75
|
"access": "public"
|
|
76
|
+
},
|
|
77
|
+
"exports": {
|
|
78
|
+
".": {
|
|
79
|
+
"types": "./lib/index.d.ts",
|
|
80
|
+
"default": "./lib/index.js"
|
|
81
|
+
},
|
|
82
|
+
"./client": "./lib/client.js",
|
|
83
|
+
"./package.json": "./package.json"
|
|
70
84
|
}
|
|
71
85
|
}
|