fix: bundle Feishu SDK for script-free installs

This commit is contained in:
xmanrui 2026-08-16 15:40:37 +08:00
parent b930d59ac3
commit 5e90962b6d
9 changed files with 290 additions and 13351 deletions

View file

@ -6,10 +6,40 @@ The DingTalk device-authorization request sequence and AI Card streaming protoco
The WeCom QR-authorization request sequence is adapted from the official [`@wecom/wecom-openclaw-cli`](https://www.npmjs.com/package/@wecom/wecom-openclaw-cli) 1.1.0 package, whose npm metadata declares the ISC License. No CLI source or OpenClaw runtime is bundled in this package.
This package depends on [`@larksuiteoapi/node-sdk`](https://github.com/larksuite/node-sdk) 1.73.0, [`dingtalk-stream`](https://github.com/open-dingtalk/dingtalk-stream-sdk-nodejs) 2.1.4, [`@wecom/aibot-node-sdk`](https://github.com/WecomTeam/aibot-node-sdk) 1.0.7, [`@tencent-connect/qqbot-nodejs`](https://github.com/tencent-connect/qqbot) 1.0.4, and [`qrcode`](https://github.com/soldair/node-qrcode) 1.5.4. These packages are licensed under the MIT License; `dingtalk-stream` is copyright 2023 钉钉开放平台团队.
The Host bundle includes [`@larksuiteoapi/node-sdk`](https://github.com/larksuite/node-sdk) 1.73.0 and its [`protobufjs`](https://github.com/protobufjs/protobuf.js) 7.6.5 runtime. The Lark SDK is licensed under the MIT License. protobufjs is licensed under the BSD 3-Clause License; both license texts are reproduced below.
This package depends at runtime on [`dingtalk-stream`](https://github.com/open-dingtalk/dingtalk-stream-sdk-nodejs) 2.1.4, [`@wecom/aibot-node-sdk`](https://github.com/WecomTeam/aibot-node-sdk) 1.0.7, [`@tencent-connect/qqbot-nodejs`](https://github.com/tencent-connect/qqbot) 1.0.4, and [`qrcode`](https://github.com/soldair/node-qrcode) 1.5.4. These packages are licensed under the MIT License; `dingtalk-stream` is copyright 2023 钉钉开放平台团队.
QQ QR binding uses Tencent Connect's official [`@tencent-connect/qqbot-connector`](https://www.npmjs.com/package/@tencent-connect/qqbot-connector) 1.2.0 package as an external runtime dependency. Its npm metadata declares `UNLICENSED`; no connector source is copied into this project.
This project is an independent DeepSeek Harness integration. It does not bundle OpenClaw and is not endorsed by Tencent, WeCom, Feishu, DingTalk, QQ, Telegram, or Discord.
The WeChat, QQ, Telegram, and Discord marks use path data published by Simple Icons under the CC0 1.0 Universal license. The Feishu, DingTalk, and WeCom marks are inline vectors used for channel identification. Product names and logos remain trademarks of their respective owners.
## Lark Node SDK license
MIT License
Copyright (c) 2022 Lark Technologies Pte. Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice, shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## protobufjs license
This license applies to all parts of protobuf.js except those files either explicitly including or referencing a different license or located in a directory containing a different LICENSE file.
Copyright (c) 2016, Daniel Wirtz All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of its author, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Code generated by the command line utilities is owned by the owner of the input file used when generating it. This code is not standalone and requires a support library to be linked with it. This support library is itself covered by the above license.

13524
lib/index.js

File diff suppressed because one or more lines are too long

30
package-lock.json generated
View file

@ -1,15 +1,14 @@
{
"name": "@xmanrui/dsh-im",
"version": "0.1.0",
"version": "0.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@xmanrui/dsh-im",
"version": "0.1.0",
"version": "0.1.1",
"license": "MIT",
"dependencies": {
"@larksuiteoapi/node-sdk": "1.73.0",
"@tencent-connect/qqbot-connector": "1.2.0",
"@tencent-connect/qqbot-nodejs": "1.0.4",
"@wecom/aibot-node-sdk": "1.0.7",
@ -20,6 +19,7 @@
"dsh-im": "bin/dsh-im.mjs"
},
"devDependencies": {
"@larksuiteoapi/node-sdk": "1.73.0",
"esbuild": "0.25.9",
"react": "18.3.1",
"react-dom": "18.3.1",
@ -475,6 +475,7 @@
"version": "1.73.0",
"resolved": "https://registry.npmjs.org/@larksuiteoapi/node-sdk/-/node-sdk-1.73.0.tgz",
"integrity": "sha512-gs4EiupJ6RdYAEJGtuYrCVsB7wSMBwtUDK+ilpmOHD6RTvbtciW6AWciQO9coOQVuBZfh7hvAi25dPfCsny/nA==",
"dev": true,
"license": "MIT",
"dependencies": {
"axios": "^1.16.0",
@ -490,30 +491,35 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/base64": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/codegen": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
"integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/eventemitter": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
"integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/fetch": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
"integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@protobufjs/aspromise": "^1.1.1"
@ -523,24 +529,28 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/path": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/pool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@protobufjs/utf8": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz",
"integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@tencent-connect/qqbot-connector": {
@ -583,6 +593,7 @@
"version": "26.2.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
"integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~8.3.0"
@ -670,6 +681,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
@ -1097,24 +1109,28 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-3.0.0.tgz",
"integrity": "sha512-AupTIzdLQxJS5wIYUQlgGyk2XRTfGXA+MCghDHqZk0pzUNYvd3EESS6dkChNauNYVIutcb0dfHw1ri9Q1yPV8Q==",
"dev": true,
"license": "MIT"
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
"license": "MIT"
},
"node_modules/lodash.pickby": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz",
"integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==",
"dev": true,
"license": "MIT"
},
"node_modules/long": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/loose-envify": {
@ -1180,6 +1196,7 @@
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@ -1246,6 +1263,7 @@
"version": "7.6.5",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz",
"integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==",
"dev": true,
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
@ -1303,6 +1321,7 @@
"version": "6.15.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
"integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"es-define-property": "^1.0.1",
@ -1414,6 +1433,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
"integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@ -1433,6 +1453,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@ -1449,6 +1470,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@ -1467,6 +1489,7 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@ -1512,6 +1535,7 @@
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
"dev": true,
"license": "MIT"
},
"node_modules/which-module": {

View file

@ -1,6 +1,6 @@
{
"name": "@xmanrui/dsh-im",
"version": "0.1.0",
"version": "0.1.1",
"description": "通过扫码或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Telegram和Discord)。",
"license": "MIT",
"type": "module",
@ -57,7 +57,6 @@
"node": ">=22.19"
},
"dependencies": {
"@larksuiteoapi/node-sdk": "1.73.0",
"@tencent-connect/qqbot-connector": "1.2.0",
"@tencent-connect/qqbot-nodejs": "1.0.4",
"@wecom/aibot-node-sdk": "1.0.7",
@ -65,6 +64,7 @@
"qrcode": "1.5.4"
},
"devDependencies": {
"@larksuiteoapi/node-sdk": "1.73.0",
"esbuild": "0.25.9",
"react": "18.3.1",
"react-dom": "18.3.1",

View file

@ -7,6 +7,14 @@ import { build } from 'esbuild';
const sourceDirectory = dirname(fileURLToPath(import.meta.url));
const packageRoot = resolve(sourceDirectory, '../..');
const outputPath = resolve(packageRoot, 'lib/index.js');
const externalRuntimePackages = [
'@tencent-connect/qqbot-connector',
'@tencent-connect/qqbot-nodejs',
'@wecom/aibot-node-sdk',
'dingtalk-stream',
'qrcode',
];
const external = externalRuntimePackages.flatMap((name) => [name, `${name}/*`]);
await mkdir(dirname(outputPath), { recursive: true });
await build({
@ -15,10 +23,22 @@ await build({
format: 'esm',
platform: 'node',
target: ['node22'],
packages: 'external',
mainFields: ['module', 'main'],
external,
outfile: outputPath,
banner: {
js: [
"import { createRequire as __dshCreateRequire } from 'node:module';",
"import { dirname as __dshDirname } from 'node:path';",
"import { fileURLToPath as __dshFileURLToPath } from 'node:url';",
'const require = __dshCreateRequire(import.meta.url);',
'const __filename = __dshFileURLToPath(import.meta.url);',
'const __dirname = __dshDirname(__filename);',
].join('\n'),
},
sourcemap: false,
legalComments: 'none',
minify: true,
legalComments: 'eof',
});
console.log(`Wrote ${outputPath}`);

View file

@ -1,5 +1,6 @@
import { access, readFile, stat } from 'node:fs/promises';
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
const root = resolve(import.meta.dirname, '..');
const required = [
@ -38,6 +39,7 @@ const [client, host, patch, manifestText, lockText, hostSource, clientSource, ex
stat(resolve(root, 'bin/dsh-im.mjs')),
]);
const manifest = JSON.parse(manifestText);
const lock = JSON.parse(lockText);
if (!client.includes('id: "@xmanrui/dsh-im"')) {
throw new Error('client bundle does not register the dsh-im loader id');
@ -77,7 +79,6 @@ for (const name of ['@xmanrui/dsh-feishu', '@xmanrui/dsh-weixin', '@xmanrui/dsh-
}
}
const directDependencies = {
'@larksuiteoapi/node-sdk': '1.73.0',
'dingtalk-stream': '2.1.4',
'@tencent-connect/qqbot-connector': '1.2.0',
'@tencent-connect/qqbot-nodejs': '1.0.4',
@ -89,9 +90,27 @@ for (const [name, version] of Object.entries(directDependencies)) {
throw new Error(`${name} must be a pinned direct dependency at ${version}`);
}
}
const bundledBuildDependencies = {
'@larksuiteoapi/node-sdk': '1.73.0',
};
for (const [name, version] of Object.entries(bundledBuildDependencies)) {
if (manifest.dependencies?.[name] !== undefined) {
throw new Error(`${name} must not remain a runtime dependency`);
}
if (manifest.devDependencies?.[name] !== version) {
throw new Error(`${name} must be a pinned build dependency at ${version}`);
}
}
if (lock.packages?.['node_modules/protobufjs']?.dev !== true) {
throw new Error('protobufjs must remain build-only in the package lock');
}
if (/(?:from\s*|import\s*\(|require\s*\()\s*["'](?:@larksuiteoapi\/node-sdk|protobufjs)(?:\/[^"']*)?["']/.test(host)) {
throw new Error('host bundle must not import the Feishu SDK or protobufjs at runtime');
}
if ((executable.mode & 0o111) === 0) throw new Error('dsh-im CLI is not executable');
if (/private-bot-token|must-be-rolled-back|DEEPSEEK_API_KEY=/.test(client + host)) {
throw new Error('built artifacts contain a test or environment secret marker');
}
await import(pathToFileURL(resolve(root, 'lib/index.js')).href);
console.log('Verified dsh-im package artifacts.');

View file

@ -108,7 +108,7 @@ export class DiscordApi {
headers: {
authorization: `Bot ${this.#token}`,
'content-type': 'application/json',
'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.1.0)',
'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.1.1)',
},
...(body === undefined ? {} : { body: JSON.stringify(body) }),
signal: requestSignal(signal, timeoutMs),

View file

@ -92,7 +92,7 @@ function authenticatedHeaders(token) {
function baseInfo() {
return {
channel_version: WEIXIN_PROTOCOL_VERSION,
bot_agent: 'DeepSeekHarness/0.1.0',
bot_agent: 'DeepSeekHarness/0.1.1',
};
}

View file

@ -93,7 +93,7 @@ test('sendText emits the iLink message envelope without reflecting the token in
assert.equal(body.msg.context_token, 'message-context');
assert.equal(body.msg.item_list[0].text_item.text, 'Harness reply');
assert.equal(body.base_info.channel_version, '2.4.6');
assert.equal(body.base_info.bot_agent, 'DeepSeekHarness/0.1.0');
assert.equal(body.base_info.bot_agent, 'DeepSeekHarness/0.1.1');
assert.doesNotMatch(calls[0].init.body, /host-only-token/);
});