@thewaifu/dsh-bot 1.1.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/LICENSE +201 -0
- package/README.md +304 -0
- package/bin/dsh-bot-web.js +33 -0
- package/client.js +13691 -0
- package/cordis.patch.yml +17 -0
- package/index.js +57 -0
- package/package.json +80 -0
- package/src/host/agents.js +186 -0
- package/src/host/approvals.js +63 -0
- package/src/host/browser.js +258 -0
- package/src/host/channel.js +342 -0
- package/src/host/chat-index.js +293 -0
- package/src/host/connectors.js +169 -0
- package/src/host/constants.js +65 -0
- package/src/host/delivery.js +71 -0
- package/src/host/diagnostics.js +249 -0
- package/src/host/dsh-compat.js +22 -0
- package/src/host/dsh-update.js +170 -0
- package/src/host/groups.js +592 -0
- package/src/host/home-lock.js +97 -0
- package/src/host/images.js +211 -0
- package/src/host/memory.js +1362 -0
- package/src/host/models.js +231 -0
- package/src/host/parts.js +976 -0
- package/src/host/permissions.js +48 -0
- package/src/host/prompt.js +71 -0
- package/src/host/roster.js +471 -0
- package/src/host/schedules.js +151 -0
- package/src/host/secrets.js +530 -0
- package/src/host/steward.js +164 -0
- package/src/host/store.js +344 -0
- package/src/host/text.js +47 -0
- package/src/host/time-context.js +46 -0
- package/src/host/tools.js +425 -0
- package/src/host/turns.js +388 -0
- package/src/host/update.js +237 -0
- package/src/host/usage.js +591 -0
- package/src/host/waifu.js +58 -0
- package/src/shared/mentions.js +65 -0
- package/src/shared/web-port.js +26 -0
- package/web-search.js +764 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// DSH updates: a released DS Bot may name the DSH release it was verified
|
|
2
|
+
// against (`dsBot.verifiedDsh` in package.json); a release that names none
|
|
3
|
+
// offers nothing. The newest released bot wins: offering that version and
|
|
4
|
+
// nothing newer keeps the update path away from DSH releases we have not
|
|
5
|
+
// checked. A DSH installed from npm swaps with `npm i -g`; a packaged app's
|
|
6
|
+
// runtime lives inside its bundle and only its own updater moves it, to the
|
|
7
|
+
// newest release it finds, so the client offers it only when that release is
|
|
8
|
+
// the verified one.
|
|
9
|
+
import { spawn } from 'node:child_process'
|
|
10
|
+
import { readFileSync } from 'node:fs'
|
|
11
|
+
import { dirname, join } from 'node:path'
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
CHECK_TTL_MS, cleanVersion, encodeName, fetchJson, installSpecOf,
|
|
15
|
+
newer, registryPlan, repoSlug, sourceOf,
|
|
16
|
+
} from './update.js'
|
|
17
|
+
|
|
18
|
+
const PKG = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8'))
|
|
19
|
+
const APP_BOOT = '@deepseek-ai/dsh-app-boot'
|
|
20
|
+
const DSH_PACKAGE = '@deepseek-ai/dsh'
|
|
21
|
+
|
|
22
|
+
export function install(rt) {
|
|
23
|
+
const { ctx, config } = rt
|
|
24
|
+
const enabled = config.updateCheck !== false
|
|
25
|
+
|
|
26
|
+
const status = {
|
|
27
|
+
current: null, verified: null, kind: 'npm', blockedBy: null,
|
|
28
|
+
checkedAt: 0, phase: 'idle', installed: null, error: null,
|
|
29
|
+
}
|
|
30
|
+
let target = null
|
|
31
|
+
let checking = null
|
|
32
|
+
let running = null
|
|
33
|
+
|
|
34
|
+
// A newer `minBot` than the running bot gates the offer: the bot goes first.
|
|
35
|
+
const blocked = () => status.blockedBy !== null && newer(status.blockedBy, PKG.version)
|
|
36
|
+
|
|
37
|
+
const view = () => ({
|
|
38
|
+
current: status.current, verified: status.verified, kind: status.kind, blockedBy: status.blockedBy,
|
|
39
|
+
checkedAt: status.checkedAt, phase: status.phase, installed: status.installed, error: status.error,
|
|
40
|
+
// Nothing is offered without a current version to compare against.
|
|
41
|
+
available: status.phase !== 'installed' && target !== null && status.current !== null
|
|
42
|
+
&& status.verified !== null && status.verified !== status.current && !blocked(),
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// The version of the DSH that is running us: the app-boot export, or — where
|
|
46
|
+
// that import cannot see it — the nearest @deepseek-ai package.json above the
|
|
47
|
+
// entry script.
|
|
48
|
+
async function currentDsh() {
|
|
49
|
+
try {
|
|
50
|
+
const loader = ctx.get?.('loader')
|
|
51
|
+
const loaded = await loader?.import?.(APP_BOOT)
|
|
52
|
+
const appBoot = loader?.unwrapExports?.(loaded) ?? loaded?.default ?? loaded
|
|
53
|
+
const version = cleanVersion(appBoot?.getDshRuntimeVersion?.())
|
|
54
|
+
if (version) return version
|
|
55
|
+
} catch { /* the export is not visible here: read the install instead */ }
|
|
56
|
+
let dir = dirname(String(process.argv[1] ?? ''))
|
|
57
|
+
for (let depth = 0; depth < 12; depth += 1) {
|
|
58
|
+
try {
|
|
59
|
+
const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'))
|
|
60
|
+
if (manifest?.name?.startsWith?.('@deepseek-ai/')) {
|
|
61
|
+
const version = cleanVersion(manifest.version)
|
|
62
|
+
if (version) return version
|
|
63
|
+
}
|
|
64
|
+
} catch { /* not a package directory */ }
|
|
65
|
+
const parent = dirname(dir)
|
|
66
|
+
if (parent === dir) break
|
|
67
|
+
dir = parent
|
|
68
|
+
}
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// A bundled package manager means the runtime came with the app and only the
|
|
73
|
+
// app's own updater can move it.
|
|
74
|
+
const installKind = () =>
|
|
75
|
+
typeof ctx.get?.('profileContext')?.packageManager?.command === 'string' ? 'app' : 'npm'
|
|
76
|
+
|
|
77
|
+
// The newest released DS Bot's `dsBot` block, through the same channel the bot
|
|
78
|
+
// itself updates from: its registry, or the public repo's latest release.
|
|
79
|
+
async function releasedDeclaration(source) {
|
|
80
|
+
if (source.kind === 'registry') {
|
|
81
|
+
for (const registry of await registryPlan(config, ctx.get?.('pluginManager'))) {
|
|
82
|
+
try {
|
|
83
|
+
const manifest = await fetchJson(`${registry}${encodeName(PKG.name)}/latest`)
|
|
84
|
+
if (manifest?.dsBot?.verifiedDsh) return manifest.dsBot
|
|
85
|
+
} catch { /* unreachable or not published there: ask the next one */ }
|
|
86
|
+
}
|
|
87
|
+
return null
|
|
88
|
+
}
|
|
89
|
+
const repo = repoSlug()
|
|
90
|
+
if (!repo) return null
|
|
91
|
+
try {
|
|
92
|
+
const release = await fetchJson(`https://api.github.com/repos/${repo}/releases/latest`, { 'user-agent': `${PKG.name}/${PKG.version}` })
|
|
93
|
+
const tag = cleanVersion(release?.tag_name)
|
|
94
|
+
if (!tag) return null
|
|
95
|
+
const manifest = await fetchJson(`https://raw.githubusercontent.com/${repo}/${release.tag_name}/ds-bot/package.json`, { 'user-agent': `${PKG.name}/${PKG.version}` })
|
|
96
|
+
return manifest?.dsBot?.verifiedDsh ? manifest.dsBot : null
|
|
97
|
+
} catch { return null }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function runCheck() {
|
|
101
|
+
try {
|
|
102
|
+
status.current = await currentDsh()
|
|
103
|
+
status.kind = installKind()
|
|
104
|
+
// The release the running package itself verified stays the floor: a bot
|
|
105
|
+
// older than its own declaration has nothing newer to offer.
|
|
106
|
+
const declared = [{ verifiedDsh: PKG.dsBot?.verifiedDsh }]
|
|
107
|
+
const released = await releasedDeclaration(sourceOf(await installSpecOf(ctx)))
|
|
108
|
+
if (released) declared.push(released)
|
|
109
|
+
const newestDeclared = declared
|
|
110
|
+
.filter(entry => cleanVersion(entry.verifiedDsh))
|
|
111
|
+
.sort((a, b) => (newer(cleanVersion(a.verifiedDsh), cleanVersion(b.verifiedDsh)) ? -1 : 1))[0]
|
|
112
|
+
status.verified = cleanVersion(newestDeclared?.verifiedDsh)
|
|
113
|
+
// A release may gate the DSH update on a newer bot: offer nothing until
|
|
114
|
+
// the bot itself is at least `minBot`.
|
|
115
|
+
status.blockedBy = cleanVersion(newestDeclared?.minBot)
|
|
116
|
+
target = status.current !== null && status.verified !== null && status.verified !== status.current
|
|
117
|
+
? { version: status.verified }
|
|
118
|
+
: null
|
|
119
|
+
status.error = null
|
|
120
|
+
} catch (error) {
|
|
121
|
+
rt.warn('ds-bot: dsh update check failed: %s', error?.message ?? error)
|
|
122
|
+
status.verified = null
|
|
123
|
+
status.blockedBy = null
|
|
124
|
+
target = null
|
|
125
|
+
}
|
|
126
|
+
status.checkedAt = Date.now()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Read current and verified DSH versions; a fresh check ignores the last answer. */
|
|
130
|
+
async function check({ fresh = false } = {}) {
|
|
131
|
+
if (!enabled) return view()
|
|
132
|
+
if (checking) return checking
|
|
133
|
+
if (!fresh && Date.now() - status.checkedAt < CHECK_TTL_MS) return view()
|
|
134
|
+
checking = runCheck().finally(() => { checking = null })
|
|
135
|
+
await checking
|
|
136
|
+
return view()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Swap an npm-installed DSH for the verified version; the answer comes back through `check`. */
|
|
140
|
+
function start() {
|
|
141
|
+
if (status.phase === 'installing') return view()
|
|
142
|
+
if (target === null || blocked()) throw new Error('No DSH update is available')
|
|
143
|
+
if (status.kind !== 'npm') throw new Error('This DSH updates with its app')
|
|
144
|
+
const chosen = target
|
|
145
|
+
Object.assign(status, { phase: 'installing', error: null })
|
|
146
|
+
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
147
|
+
const args = ['install', '-g', `${DSH_PACKAGE}@${chosen.version}`]
|
|
148
|
+
const runner = rt.dshSpawn ?? ((command, argv, options) => spawn(command, argv, options))
|
|
149
|
+
running = runner(npm, args, { windowsHide: true })
|
|
150
|
+
let output = ''
|
|
151
|
+
running.stdout?.on?.('data', chunk => { output = `${output}${chunk}`.slice(-4000) })
|
|
152
|
+
running.stderr?.on?.('data', chunk => { output = `${output}${chunk}`.slice(-4000) })
|
|
153
|
+
const done = new Promise((resolve, reject) => {
|
|
154
|
+
running.once?.('error', reject)
|
|
155
|
+
running.once?.('close', code => (code === 0 ? resolve() : reject(new Error(`npm exited ${code}`))))
|
|
156
|
+
})
|
|
157
|
+
void done
|
|
158
|
+
.then(() => Object.assign(status, { phase: 'installed', installed: chosen.version }))
|
|
159
|
+
.catch((error) => {
|
|
160
|
+
rt.warn('ds-bot: dsh update to %s failed: %s', chosen.version, error?.message ?? error)
|
|
161
|
+
Object.assign(status, { phase: 'failed', error: `${error?.message ?? error}${output ? ` — ${output.trim().slice(-400)}` : ''}`.slice(0, 600) })
|
|
162
|
+
})
|
|
163
|
+
return view()
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Whatever npm is still running when the plugin unloads dies with it.
|
|
167
|
+
ctx.effect(() => () => running?.kill?.(), 'ds-bot: dsh update install')
|
|
168
|
+
|
|
169
|
+
Object.assign(rt, { dshUpdateCheck: check, dshUpdateStart: start, dshUpdateView: view })
|
|
170
|
+
}
|