dsh-lark-bot 0.15.5 → 0.15.7
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/README.md +4 -1
- package/dist/cli.js +242 -67
- package/dist/cli.js.map +1 -1
- package/dist/plugin.d.ts +8 -0
- package/dist/plugin.js +242 -67
- package/dist/plugin.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -163,9 +163,12 @@ dsh-lark-bot guardian install --dsh-profile dsh-lark
|
|
|
163
163
|
字面密钥不进 settings / 聊天记录。
|
|
164
164
|
- **凭据引用必须关联**:`/key set <引用名> <值>` 只写入凭据文件;provider 要生效还须在其
|
|
165
165
|
`apiKeyEnv` 字段引用同一名字(`/provider add|update ... --api-key-env <引用名>`,或向导中填写)。
|
|
166
|
+
引用名与 provider ID 相同且 provider 未设 `apiKeyEnv` 时,`/key set` 会自动补关联;
|
|
167
|
+
已存在的老配置在下次运行时也会自动补齐。
|
|
166
168
|
- **热重载**:桥接在每轮运行前把模型解析为「provider + model」路由并传给 dsh runtime;SDK 适配器
|
|
167
169
|
在路由变化时自动重建 runtime(下一轮生效)。pi-ai 的 Base URL 填根域名(如
|
|
168
|
-
`https://www.kingapi.xyz`)会自动补全为 `/v1`。
|
|
170
|
+
`https://www.kingapi.xyz`)会自动补全为 `/v1`。dsh runtime 启动后需几百毫秒才注册
|
|
171
|
+
pi-ai 路由,桥接会重试握手直到注册完成(避免 “no adapter registered for provider”)。
|
|
169
172
|
|
|
170
173
|
安全提醒:在飞书会话输入密钥会对可见成员暴露,建议私聊使用或 `--api-key-env` 引用环境变量;bot 不在任何回复中回显密钥值。
|
|
171
174
|
|
package/dist/cli.js
CHANGED
|
@@ -1256,6 +1256,52 @@ function createSdkRun(harness, prompt, options) {
|
|
|
1256
1256
|
}
|
|
1257
1257
|
|
|
1258
1258
|
// src/adapters/dsh/sdk-adapter.ts
|
|
1259
|
+
var RETRYABLE_INIT_ERROR = /no adapter registered for provider/i;
|
|
1260
|
+
var INIT_RETRY_ATTEMPTS = 6;
|
|
1261
|
+
var INIT_RETRY_DELAY_MS = 250;
|
|
1262
|
+
function sleep(ms) {
|
|
1263
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1264
|
+
}
|
|
1265
|
+
function isRetryableInitError(error) {
|
|
1266
|
+
return error instanceof Error && RETRYABLE_INIT_ERROR.test(error.message);
|
|
1267
|
+
}
|
|
1268
|
+
function withRetryableStart(harness) {
|
|
1269
|
+
const originalStart = harness.start.bind(harness);
|
|
1270
|
+
const internals = harness;
|
|
1271
|
+
let handled = false;
|
|
1272
|
+
harness.start = async () => {
|
|
1273
|
+
if (handled) return originalStart();
|
|
1274
|
+
try {
|
|
1275
|
+
const result = await originalStart();
|
|
1276
|
+
handled = true;
|
|
1277
|
+
return result;
|
|
1278
|
+
} catch (error) {
|
|
1279
|
+
if (!isRetryableInitError(error)) throw error;
|
|
1280
|
+
handled = true;
|
|
1281
|
+
const client = internals.client;
|
|
1282
|
+
if (!client) throw error;
|
|
1283
|
+
client.start();
|
|
1284
|
+
let lastError = error;
|
|
1285
|
+
for (let attempt = 1; attempt <= INIT_RETRY_ATTEMPTS; attempt += 1) {
|
|
1286
|
+
await sleep(INIT_RETRY_DELAY_MS * attempt);
|
|
1287
|
+
try {
|
|
1288
|
+
await client.initialize({
|
|
1289
|
+
cwd: internals.cwd,
|
|
1290
|
+
provider: internals.provider,
|
|
1291
|
+
model: internals.model
|
|
1292
|
+
});
|
|
1293
|
+
internals.initialized = Promise.resolve();
|
|
1294
|
+
return void 0;
|
|
1295
|
+
} catch (retryError) {
|
|
1296
|
+
lastError = retryError;
|
|
1297
|
+
if (!isRetryableInitError(retryError)) throw retryError;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
throw lastError;
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
return harness;
|
|
1304
|
+
}
|
|
1259
1305
|
function waitWithTimeout(promise, timeoutMs) {
|
|
1260
1306
|
return new Promise((resolve5) => {
|
|
1261
1307
|
const timer = setTimeout(() => resolve5(false), timeoutMs > 0 ? timeoutMs : 5e3);
|
|
@@ -1308,21 +1354,35 @@ var SdkDshAdapter = class {
|
|
|
1308
1354
|
});
|
|
1309
1355
|
try {
|
|
1310
1356
|
client.start();
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1357
|
+
let lastError;
|
|
1358
|
+
for (let attempt = 1; attempt <= INIT_RETRY_ATTEMPTS; attempt += 1) {
|
|
1359
|
+
try {
|
|
1360
|
+
const info = await client.initialize({
|
|
1361
|
+
cwd: process.cwd(),
|
|
1362
|
+
provider: this.provider,
|
|
1363
|
+
model: this.model,
|
|
1364
|
+
...this.maxTokens === void 0 ? {} : { maxTokens: this.maxTokens }
|
|
1365
|
+
});
|
|
1366
|
+
return {
|
|
1367
|
+
ok: true,
|
|
1368
|
+
error: void 0,
|
|
1369
|
+
version: `${info.serverInfo.name}@${info.serverInfo.version}`
|
|
1370
|
+
};
|
|
1371
|
+
} catch (error) {
|
|
1372
|
+
lastError = error;
|
|
1373
|
+
if (!isRetryableInitError(error) || attempt === INIT_RETRY_ATTEMPTS) {
|
|
1374
|
+
return {
|
|
1375
|
+
ok: false,
|
|
1376
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1377
|
+
version: void 0
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
await sleep(INIT_RETRY_DELAY_MS * attempt);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1323
1383
|
return {
|
|
1324
1384
|
ok: false,
|
|
1325
|
-
error:
|
|
1385
|
+
error: lastError instanceof Error ? lastError.message : String(lastError),
|
|
1326
1386
|
version: void 0
|
|
1327
1387
|
};
|
|
1328
1388
|
} finally {
|
|
@@ -1408,7 +1468,7 @@ var SdkDshAdapter = class {
|
|
|
1408
1468
|
}
|
|
1409
1469
|
}
|
|
1410
1470
|
const entry = {
|
|
1411
|
-
harness: this.harnessFactory(cwd, route),
|
|
1471
|
+
harness: withRetryableStart(this.harnessFactory(cwd, route)),
|
|
1412
1472
|
provider: route.provider,
|
|
1413
1473
|
model: route.model,
|
|
1414
1474
|
active: 0,
|
|
@@ -3890,7 +3950,19 @@ function renderApprovalCard(input) {
|
|
|
3890
3950
|
body: {
|
|
3891
3951
|
elements: [
|
|
3892
3952
|
{ tag: "markdown", content: markdown2 },
|
|
3893
|
-
|
|
3953
|
+
...actions.length > 0 ? [
|
|
3954
|
+
{
|
|
3955
|
+
tag: "column_set",
|
|
3956
|
+
flex_mode: "none",
|
|
3957
|
+
horizontal_spacing: "default",
|
|
3958
|
+
columns: actions.map((button2) => ({
|
|
3959
|
+
tag: "column",
|
|
3960
|
+
width: "auto",
|
|
3961
|
+
vertical_align: "center",
|
|
3962
|
+
elements: [button2]
|
|
3963
|
+
}))
|
|
3964
|
+
}
|
|
3965
|
+
] : []
|
|
3894
3966
|
]
|
|
3895
3967
|
}
|
|
3896
3968
|
};
|
|
@@ -3933,15 +4005,18 @@ function renderQuestionCard(input) {
|
|
|
3933
4005
|
body: {
|
|
3934
4006
|
elements: [
|
|
3935
4007
|
{ tag: "markdown", content: `\u2753 ${input.question}` },
|
|
3936
|
-
formElement(input),
|
|
3937
4008
|
{
|
|
3938
|
-
tag: "
|
|
3939
|
-
|
|
4009
|
+
tag: "form",
|
|
4010
|
+
name: `form-${input.id}`,
|
|
4011
|
+
elements: [
|
|
4012
|
+
formElement(input),
|
|
3940
4013
|
{
|
|
3941
4014
|
tag: "button",
|
|
3942
4015
|
text: { tag: "plain_text", content: "\u63D0\u4EA4" },
|
|
3943
4016
|
type: "primary",
|
|
3944
|
-
value: { cmd: "question-submit", id: input.id }
|
|
4017
|
+
value: { cmd: "question-submit", id: input.id },
|
|
4018
|
+
form_action_type: "submit",
|
|
4019
|
+
name: `btn-submit-${input.id}`
|
|
3945
4020
|
}
|
|
3946
4021
|
]
|
|
3947
4022
|
}
|
|
@@ -4495,7 +4570,7 @@ async function readOptional(file) {
|
|
|
4495
4570
|
throw error;
|
|
4496
4571
|
}
|
|
4497
4572
|
}
|
|
4498
|
-
function
|
|
4573
|
+
function sleep2(ms) {
|
|
4499
4574
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
4500
4575
|
}
|
|
4501
4576
|
async function withFileLock(filename, operation) {
|
|
@@ -4511,7 +4586,7 @@ async function withFileLock(filename, operation) {
|
|
|
4511
4586
|
if (Date.now() >= deadline) {
|
|
4512
4587
|
throw new Error(`dsh config lock timed out at ${lockPath}`);
|
|
4513
4588
|
}
|
|
4514
|
-
await
|
|
4589
|
+
await sleep2(80 + Math.random() * 120);
|
|
4515
4590
|
}
|
|
4516
4591
|
}
|
|
4517
4592
|
try {
|
|
@@ -4742,6 +4817,25 @@ var DshProviderManager = class {
|
|
|
4742
4817
|
}
|
|
4743
4818
|
return true;
|
|
4744
4819
|
}
|
|
4820
|
+
/**
|
|
4821
|
+
* Heal the common misconfiguration where a credential was stored under the
|
|
4822
|
+
* provider id (`/key set kingapi …`) but the provider never got an
|
|
4823
|
+
* apiKeyEnv. Links the ref to the matching pi-ai provider once; returns
|
|
4824
|
+
* true when a link was applied. Idempotent and a no-op when the provider
|
|
4825
|
+
* already has a ref or no matching credential exists.
|
|
4826
|
+
*/
|
|
4827
|
+
async linkCredentialRefIfMissing(providerId) {
|
|
4828
|
+
const settings = await this.readSettings();
|
|
4829
|
+
const piAi = isMapLike(settings[PIAI_NAMESPACE]) ? settings[PIAI_NAMESPACE] : {};
|
|
4830
|
+
const providers = isMapLike(piAi.providers) ? piAi.providers : {};
|
|
4831
|
+
const section = isMapLike(providers[providerId]) ? providers[providerId] : {};
|
|
4832
|
+
if (typeof section.apiKeyEnv === "string" && section.apiKeyEnv.length > 0) {
|
|
4833
|
+
return false;
|
|
4834
|
+
}
|
|
4835
|
+
if (!await this.hasCredential(providerId)) return false;
|
|
4836
|
+
await this.upsertPiAiProvider({ id: providerId, apiKeyEnv: providerId });
|
|
4837
|
+
return true;
|
|
4838
|
+
}
|
|
4745
4839
|
async addPiAiModel(providerId, input) {
|
|
4746
4840
|
validateProviderId(providerId);
|
|
4747
4841
|
const settings = await this.readSettings();
|
|
@@ -5127,9 +5221,24 @@ async function handleKey(args, ctx) {
|
|
|
5127
5221
|
await reply(ctx, `\u5199\u5165\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
|
|
5128
5222
|
return;
|
|
5129
5223
|
}
|
|
5224
|
+
const providers = await ctx.dshConfig.listProviders();
|
|
5225
|
+
const target = providers.find(
|
|
5226
|
+
(provider) => provider.id === ref && provider.namespace === PIAI_NAMESPACE && provider.credentialRef === void 0
|
|
5227
|
+
);
|
|
5228
|
+
let autoLinked = false;
|
|
5229
|
+
if (target) {
|
|
5230
|
+
await ctx.dshConfig.upsertPiAiProvider({ id: ref, apiKeyEnv: ref });
|
|
5231
|
+
autoLinked = true;
|
|
5232
|
+
}
|
|
5130
5233
|
await reply(
|
|
5131
5234
|
ctx,
|
|
5132
|
-
|
|
5235
|
+
[
|
|
5236
|
+
`\u5DF2\u5199\u5165\u51ED\u636E \`${ref}\` \u5230 \`~/.dsh/.credentials.yaml\`\uFF080600\uFF0C\u503C\u5DF2\u9690\u85CF\uFF09\u3002\u5EFA\u8BAE\u5728\u79C1\u804A\u4E2D\u4F7F\u7528\uFF1B\u7FA4\u804A\u91CC\u7C98\u8D34\u7684\u5BC6\u94A5\u4F1A\u5BF9\u7FA4\u6210\u5458\u53EF\u89C1\u3002`,
|
|
5237
|
+
...autoLinked ? [
|
|
5238
|
+
"",
|
|
5239
|
+
`\u{1F517} \u5DF2\u81EA\u52A8\u628A provider \`${ref}\` \u7684 apiKeyEnv \u5173\u8054\u5230 \`${ref}\`\uFF08\u4E0B\u4E00\u8BF7\u6C42\u751F\u6548\uFF09\u3002`
|
|
5240
|
+
] : []
|
|
5241
|
+
].join("\n")
|
|
5133
5242
|
);
|
|
5134
5243
|
return;
|
|
5135
5244
|
}
|
|
@@ -5155,8 +5264,18 @@ function button(text, value, type = "default") {
|
|
|
5155
5264
|
value
|
|
5156
5265
|
};
|
|
5157
5266
|
}
|
|
5158
|
-
function
|
|
5159
|
-
return {
|
|
5267
|
+
function buttonRow(buttons) {
|
|
5268
|
+
return {
|
|
5269
|
+
tag: "column_set",
|
|
5270
|
+
flex_mode: "none",
|
|
5271
|
+
horizontal_spacing: "default",
|
|
5272
|
+
columns: buttons.map((button2) => ({
|
|
5273
|
+
tag: "column",
|
|
5274
|
+
width: "auto",
|
|
5275
|
+
vertical_align: "center",
|
|
5276
|
+
elements: [button2]
|
|
5277
|
+
}))
|
|
5278
|
+
};
|
|
5160
5279
|
}
|
|
5161
5280
|
function wizardValue(flow, step, extra) {
|
|
5162
5281
|
return { cmd: "wizard", flow, step, ...extra };
|
|
@@ -5187,22 +5306,22 @@ function renderConfigHubCard(input) {
|
|
|
5187
5306
|
`dsh \u9ED8\u8BA4\u6A21\u578B\uFF1A${defaultLine}`
|
|
5188
5307
|
].join("\n")
|
|
5189
5308
|
},
|
|
5190
|
-
|
|
5309
|
+
buttonRow([
|
|
5191
5310
|
button("\u2795 \u6DFB\u52A0 Provider", { cmd: "cfg", action: "provider-add" }, "primary"),
|
|
5192
5311
|
button("\u270F\uFE0F \u4FEE\u6539 Provider", { cmd: "cfg", action: "provider-update" }),
|
|
5193
5312
|
button("\u{1F5D1} \u5220\u9664 Provider", { cmd: "cfg", action: "provider-remove" }, "danger")
|
|
5194
5313
|
]),
|
|
5195
|
-
|
|
5314
|
+
buttonRow([
|
|
5196
5315
|
button("\u{1F9E0} \u6DFB\u52A0\u6A21\u578B", { cmd: "cfg", action: "model-add" }),
|
|
5197
5316
|
button("\u274C \u5220\u9664\u6A21\u578B", { cmd: "cfg", action: "model-remove" }, "danger"),
|
|
5198
5317
|
button("\u{1F3AF} \u5207\u6362\u6A21\u578B", { cmd: "cfg", action: "model-use" })
|
|
5199
5318
|
]),
|
|
5200
|
-
|
|
5319
|
+
buttonRow([
|
|
5201
5320
|
button("\u{1F3E0} \u8BBE\u7F6E\u9ED8\u8BA4\u6A21\u578B", { cmd: "cfg", action: "model-default" }),
|
|
5202
5321
|
button("\u{1F511} \u8BBE\u7F6E\u51ED\u636E", { cmd: "cfg", action: "key-set" }),
|
|
5203
5322
|
button("\u{1F513} \u5220\u9664\u51ED\u636E", { cmd: "cfg", action: "key-remove" }, "danger")
|
|
5204
5323
|
]),
|
|
5205
|
-
|
|
5324
|
+
buttonRow([
|
|
5206
5325
|
button("\u{1F504} \u5237\u65B0", { cmd: "cfg", action: "refresh" }),
|
|
5207
5326
|
button("\u2716\uFE0F \u5173\u95ED", { cmd: "cfg", action: "dismiss" })
|
|
5208
5327
|
])
|
|
@@ -5215,13 +5334,14 @@ function renderWizardOptionsCard(input) {
|
|
|
5215
5334
|
const rows = [];
|
|
5216
5335
|
for (let index = 0; index < input.options.length; index += 3) {
|
|
5217
5336
|
rows.push(
|
|
5218
|
-
|
|
5337
|
+
buttonRow(
|
|
5219
5338
|
input.options.slice(index, index + 3).map(
|
|
5220
5339
|
(option, offset) => button(option.label, wizardValue(input.flow, input.step, { choose: index + offset }))
|
|
5221
5340
|
)
|
|
5222
5341
|
)
|
|
5223
5342
|
);
|
|
5224
5343
|
}
|
|
5344
|
+
rows.push(buttonRow([cancel]));
|
|
5225
5345
|
return {
|
|
5226
5346
|
schema: "2.0",
|
|
5227
5347
|
config: {
|
|
@@ -5234,8 +5354,7 @@ function renderWizardOptionsCard(input) {
|
|
|
5234
5354
|
content: [input.question, input.hint ? `
|
|
5235
5355
|
${input.hint}` : ""].join("")
|
|
5236
5356
|
},
|
|
5237
|
-
...rows
|
|
5238
|
-
actionRow([cancel])
|
|
5357
|
+
...rows
|
|
5239
5358
|
]
|
|
5240
5359
|
}
|
|
5241
5360
|
};
|
|
@@ -5254,14 +5373,23 @@ function renderWizardTextStepCard(input) {
|
|
|
5254
5373
|
${input.hint}` : ""].join("")
|
|
5255
5374
|
},
|
|
5256
5375
|
{
|
|
5257
|
-
tag: "
|
|
5258
|
-
name:
|
|
5259
|
-
|
|
5376
|
+
tag: "form",
|
|
5377
|
+
name: `form-${input.flow}-${input.step}`,
|
|
5378
|
+
elements: [
|
|
5379
|
+
{
|
|
5380
|
+
tag: "input",
|
|
5381
|
+
name: "answer",
|
|
5382
|
+
...input.required === true ? { required: true } : {},
|
|
5383
|
+
placeholder: { tag: "plain_text", content: input.placeholder ?? "\u8BF7\u8F93\u5165\u2026" }
|
|
5384
|
+
},
|
|
5385
|
+
{
|
|
5386
|
+
...button("\u63D0\u4EA4", wizardValue(input.flow, input.step, { submit: true }), "primary"),
|
|
5387
|
+
form_action_type: "submit",
|
|
5388
|
+
name: `btn-submit-${input.flow}-${input.step}`
|
|
5389
|
+
}
|
|
5390
|
+
]
|
|
5260
5391
|
},
|
|
5261
|
-
|
|
5262
|
-
button("\u63D0\u4EA4", wizardValue(input.flow, input.step, { submit: true }), "primary"),
|
|
5263
|
-
button("\u53D6\u6D88", wizardValue(input.flow, input.step, { cancel: true }))
|
|
5264
|
-
])
|
|
5392
|
+
button("\u53D6\u6D88", wizardValue(input.flow, input.step, { cancel: true }))
|
|
5265
5393
|
]
|
|
5266
5394
|
}
|
|
5267
5395
|
};
|
|
@@ -5280,7 +5408,7 @@ function renderWizardConfirmStepCard(input) {
|
|
|
5280
5408
|
|
|
5281
5409
|
${input.summary}`
|
|
5282
5410
|
},
|
|
5283
|
-
|
|
5411
|
+
buttonRow([
|
|
5284
5412
|
button(input.confirmLabel ?? "\u2705 \u786E\u8BA4", wizardValue(input.flow, input.step, { confirm: true }), "primary"),
|
|
5285
5413
|
button("\u53D6\u6D88", wizardValue(input.flow, input.step, { cancel: true }))
|
|
5286
5414
|
])
|
|
@@ -5788,7 +5916,22 @@ var FLOWS = {
|
|
|
5788
5916
|
const ref = asString(data.ref);
|
|
5789
5917
|
const value = asString(data.value);
|
|
5790
5918
|
await ctx.dshConfig.setCredential(ref, value);
|
|
5791
|
-
|
|
5919
|
+
const providers = await ctx.dshConfig.listProviders();
|
|
5920
|
+
const target = providers.find(
|
|
5921
|
+
(provider) => provider.id === ref && provider.namespace === "llm-pi-ai" && provider.credentialRef === void 0
|
|
5922
|
+
);
|
|
5923
|
+
let autoLinked = false;
|
|
5924
|
+
if (target) {
|
|
5925
|
+
await ctx.dshConfig.upsertPiAiProvider({ id: ref, apiKeyEnv: ref });
|
|
5926
|
+
autoLinked = true;
|
|
5927
|
+
}
|
|
5928
|
+
return [
|
|
5929
|
+
`\u5DF2\u5199\u5165\u51ED\u636E \`${ref}\` \u5230 \`~/.dsh/.credentials.yaml\`\uFF080600\uFF0C\u503C\u5DF2\u9690\u85CF\uFF09\u3002\u5EFA\u8BAE\u5728\u79C1\u804A\u4E2D\u4F7F\u7528\uFF1B\u7FA4\u804A\u91CC\u7C98\u8D34\u7684\u5BC6\u94A5\u4F1A\u5BF9\u7FA4\u6210\u5458\u53EF\u89C1\u3002`,
|
|
5930
|
+
...autoLinked ? [
|
|
5931
|
+
"",
|
|
5932
|
+
`\u{1F517} \u5DF2\u81EA\u52A8\u628A provider \`${ref}\` \u7684 apiKeyEnv \u5173\u8054\u5230 \`${ref}\`\uFF08\u4E0B\u4E00\u8BF7\u6C42\u751F\u6548\uFF09\u3002`
|
|
5933
|
+
] : []
|
|
5934
|
+
].join("\n");
|
|
5792
5935
|
}
|
|
5793
5936
|
},
|
|
5794
5937
|
"key-remove": {
|
|
@@ -5844,17 +5987,24 @@ async function renderCurrentStep(ctx, state) {
|
|
|
5844
5987
|
const options = await stepOptions(step, ctx, state.data);
|
|
5845
5988
|
if (step.kind === "options" && options) {
|
|
5846
5989
|
if (ctx.channel.sendCard) {
|
|
5847
|
-
|
|
5848
|
-
ctx.
|
|
5849
|
-
|
|
5990
|
+
try {
|
|
5991
|
+
await ctx.channel.sendCard(
|
|
5992
|
+
ctx.chatId,
|
|
5993
|
+
renderWizardOptionsCard({
|
|
5994
|
+
flow: flow.id,
|
|
5995
|
+
step: state.step,
|
|
5996
|
+
question: step.question,
|
|
5997
|
+
options,
|
|
5998
|
+
...step.hint === void 0 ? {} : { hint: step.hint }
|
|
5999
|
+
})
|
|
6000
|
+
);
|
|
6001
|
+
return;
|
|
6002
|
+
} catch (error) {
|
|
6003
|
+
log.warn("wizard", "card-send-failed", {
|
|
5850
6004
|
flow: flow.id,
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
...step.hint === void 0 ? {} : { hint: step.hint }
|
|
5855
|
-
})
|
|
5856
|
-
);
|
|
5857
|
-
return;
|
|
6005
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6006
|
+
});
|
|
6007
|
+
}
|
|
5858
6008
|
}
|
|
5859
6009
|
const labels = options.map((option) => `\`${option.label}\``).join("\u3001");
|
|
5860
6010
|
await ctx.channel.sendMarkdown(
|
|
@@ -5868,17 +6018,25 @@ ${labels}
|
|
|
5868
6018
|
return;
|
|
5869
6019
|
}
|
|
5870
6020
|
if (ctx.channel.sendCard) {
|
|
5871
|
-
|
|
5872
|
-
ctx.
|
|
5873
|
-
|
|
6021
|
+
try {
|
|
6022
|
+
await ctx.channel.sendCard(
|
|
6023
|
+
ctx.chatId,
|
|
6024
|
+
renderWizardTextStepCard({
|
|
6025
|
+
flow: flow.id,
|
|
6026
|
+
step: state.step,
|
|
6027
|
+
question: step.question,
|
|
6028
|
+
...step.optional === true ? {} : { required: true },
|
|
6029
|
+
...step.placeholder === void 0 ? {} : { placeholder: step.placeholder },
|
|
6030
|
+
...step.hint === void 0 ? {} : { hint: step.hint }
|
|
6031
|
+
})
|
|
6032
|
+
);
|
|
6033
|
+
return;
|
|
6034
|
+
} catch (error) {
|
|
6035
|
+
log.warn("wizard", "card-send-failed", {
|
|
5874
6036
|
flow: flow.id,
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
...step.hint === void 0 ? {} : { hint: step.hint }
|
|
5879
|
-
})
|
|
5880
|
-
);
|
|
5881
|
-
return;
|
|
6037
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6038
|
+
});
|
|
6039
|
+
}
|
|
5882
6040
|
}
|
|
5883
6041
|
await ctx.channel.sendMarkdown(
|
|
5884
6042
|
ctx.chatId,
|
|
@@ -6019,11 +6177,17 @@ async function showConfigHub(ctx) {
|
|
|
6019
6177
|
const defaultSelection = await ctx.dshConfig.defaultModelSelection();
|
|
6020
6178
|
const currentModel = ctx.models.get(ctx.scope) ?? ctx.defaultModel;
|
|
6021
6179
|
if (ctx.channel.sendCard) {
|
|
6022
|
-
|
|
6023
|
-
ctx.
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6180
|
+
try {
|
|
6181
|
+
await ctx.channel.sendCard(
|
|
6182
|
+
ctx.chatId,
|
|
6183
|
+
renderConfigHubCard({ providers, defaultSelection, currentModel })
|
|
6184
|
+
);
|
|
6185
|
+
return;
|
|
6186
|
+
} catch (error) {
|
|
6187
|
+
log.warn("wizard", "hub-card-send-failed", {
|
|
6188
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6189
|
+
});
|
|
6190
|
+
}
|
|
6027
6191
|
}
|
|
6028
6192
|
const lines = providers.map((provider) => {
|
|
6029
6193
|
const models = provider.models.map((model) => model.id).join(", ") || "(\u65E0)";
|
|
@@ -6956,9 +7120,17 @@ async function startChannel(deps) {
|
|
|
6956
7120
|
defaultModel: deps.defaultModel,
|
|
6957
7121
|
senderId: msg.senderId
|
|
6958
7122
|
};
|
|
6959
|
-
const handled = await tryHandleCommand(msg.content, context).catch((error) => {
|
|
7123
|
+
const handled = await tryHandleCommand(msg.content, context).catch(async (error) => {
|
|
6960
7124
|
log.fail("channel-command", error, { scope });
|
|
6961
|
-
|
|
7125
|
+
try {
|
|
7126
|
+
await commandChannel.sendMarkdown(
|
|
7127
|
+
msg.chatId,
|
|
7128
|
+
`\u26A0\uFE0F \u547D\u4EE4\u6267\u884C\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`,
|
|
7129
|
+
{ replyTo: msg.messageId }
|
|
7130
|
+
);
|
|
7131
|
+
} catch {
|
|
7132
|
+
}
|
|
7133
|
+
return true;
|
|
6962
7134
|
});
|
|
6963
7135
|
if (!handled) {
|
|
6964
7136
|
const queued = deps.pending.size(scope);
|
|
@@ -8413,6 +8585,9 @@ async function startBridgeEngine(options) {
|
|
|
8413
8585
|
);
|
|
8414
8586
|
return;
|
|
8415
8587
|
}
|
|
8588
|
+
if (modelRoute && modelRoute.provider !== DEEPSEEK_PROVIDER) {
|
|
8589
|
+
await dshConfig.linkCredentialRefIfMissing(modelRoute.provider).catch(() => void 0);
|
|
8590
|
+
}
|
|
8416
8591
|
const runInput = {
|
|
8417
8592
|
scope,
|
|
8418
8593
|
chatId: first.chatId,
|