dsh-ant 0.6.0 → 0.6.3
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 +8 -8
- package/client.js +732 -231
- package/conversation.js +244 -78
- package/delegation.js +653 -16
- package/index.js +47 -10
- package/locale/messages.json +1384 -68
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { readFile } from 'node:fs/promises'
|
|
|
6
6
|
import { installSkill, listSkills, uninstallSkill } from './skill-install.js'
|
|
7
7
|
import { readLocalDelegationSettings, recentDelegationStatus, startDelegationHost,
|
|
8
8
|
writeLocalDelegationSettings } from './delegation.js'
|
|
9
|
+
import { waitForSignal } from './conversation.js'
|
|
9
10
|
|
|
10
11
|
export const inject = []
|
|
11
12
|
|
|
@@ -29,6 +30,7 @@ const DELEGATION_GRANTS_PATH = '/api/ant-teams/delegation/grants'
|
|
|
29
30
|
const DELEGATION_ENROLLED_BOTS_PATH = '/api/ant-teams/delegation/enrolled-bots'
|
|
30
31
|
const DELEGATION_GROUPS_PATH = '/api/ant-teams/delegation/groups'
|
|
31
32
|
const DELEGATION_DM_CHAT_PATH = '/api/ant-teams/delegation/dm-chat'
|
|
33
|
+
const DELEGATION_OWNER_CHALLENGE_PATH = '/api/ant-teams/delegation/owner-challenge'
|
|
32
34
|
const DELEGATION_STATUS_PATH = '/api/ant-teams/delegation/status'
|
|
33
35
|
const DELEGATION_CARDS_PATH = '/api/ant-teams/delegation/cards'
|
|
34
36
|
const DELEGATION_RULE_RECOGNITION_PATH = '/api/ant-teams/delegation/recognize'
|
|
@@ -319,7 +321,7 @@ async function fetchDelegationBots(request, ctx) {
|
|
|
319
321
|
try {
|
|
320
322
|
const details = await service.describeBot(bot.botId)
|
|
321
323
|
return {
|
|
322
|
-
bot_id: bot.botId, name: details.account?.name || bot.botId,
|
|
324
|
+
bot_id: bot.botId, channel: bot.channel, name: details.account?.name || bot.botId,
|
|
323
325
|
fingerprint: details.account?.fingerprint,
|
|
324
326
|
connected: details.connected === true,
|
|
325
327
|
available: details.capabilities?.includes('exclusive-text-consumer')
|
|
@@ -384,14 +386,33 @@ async function fetchDelegationGrants(request, ctx, credentials, settings) {
|
|
|
384
386
|
}
|
|
385
387
|
|
|
386
388
|
async function fetchDelegationGroupSettings(request, ctx, credentials, settings, kind, getHost) {
|
|
387
|
-
const methods = kind === 'groups' ? ['GET', 'PUT'] : kind === 'dm-chat' ? ['PUT']
|
|
388
|
-
: kind === 'challenge' ? ['POST'] : ['GET', 'POST', 'DELETE']
|
|
389
|
+
const methods = kind === 'groups' ? ['GET', 'PUT'] : kind === 'dm-chat' ? ['PUT'] : ['GET', 'POST', 'DELETE']
|
|
389
390
|
if (!methods.includes(request.method)) return jsonResponse(405, { message: '请求方式不支持。' })
|
|
391
|
+
if (kind === 'challenge' && request.method === 'DELETE') {
|
|
392
|
+
const fingerprint = new URL(request.url).searchParams.get('bot_fingerprint')
|
|
393
|
+
if (typeof fingerprint !== 'string' || !/^[a-f0-9]{64}$/iu.test(fingerprint)) {
|
|
394
|
+
return jsonResponse(400, { message: '请求格式无效。' })
|
|
395
|
+
}
|
|
396
|
+
const host = getHost?.()
|
|
397
|
+
if (!host?.cancelOwnerChallenge) {
|
|
398
|
+
return jsonResponse(503, { message: '本机协作收件尚未就绪,请稍后刷新后重新生成绑定码。' })
|
|
399
|
+
}
|
|
400
|
+
return jsonResponse(200, { cancelled: host.cancelOwnerChallenge(fingerprint) })
|
|
401
|
+
}
|
|
390
402
|
let connection
|
|
391
403
|
try { connection = await readMemberConnection(credentials, settings) } catch {
|
|
392
404
|
return jsonResponse(500, { message: '无法读取 ANT 连接。' })
|
|
393
405
|
}
|
|
394
406
|
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
407
|
+
if (kind === 'challenge' && request.method === 'GET') {
|
|
408
|
+
const fingerprint = new URL(request.url).searchParams.get('bot_fingerprint')
|
|
409
|
+
if (typeof fingerprint !== 'string' || !/^[a-f0-9]{64}$/iu.test(fingerprint)) {
|
|
410
|
+
return jsonResponse(400, { message: '请求格式无效。' })
|
|
411
|
+
}
|
|
412
|
+
const status = getHost?.()?.ownerChallengeStatus?.(fingerprint)
|
|
413
|
+
if (!status) return jsonResponse(503, { message: '本机协作收件尚未就绪,请稍后刷新后重新生成绑定码。' })
|
|
414
|
+
return jsonResponse(200, status)
|
|
415
|
+
}
|
|
395
416
|
let body = null
|
|
396
417
|
if (request.method !== 'GET') {
|
|
397
418
|
try {
|
|
@@ -400,7 +421,7 @@ async function fetchDelegationGroupSettings(request, ctx, credentials, settings,
|
|
|
400
421
|
body = JSON.parse(raw)
|
|
401
422
|
} catch { return jsonResponse(400, { message: '请求格式无效。' }) }
|
|
402
423
|
}
|
|
403
|
-
if (
|
|
424
|
+
if (['bots', 'challenge'].includes(kind) && request.method === 'POST') {
|
|
404
425
|
const service = dshImService(ctx)
|
|
405
426
|
if (!service?.describeBot) return jsonResponse(503, { message: '请先安装并启用 DSH-IM。' })
|
|
406
427
|
try {
|
|
@@ -417,6 +438,7 @@ async function fetchDelegationGroupSettings(request, ctx, credentials, settings,
|
|
|
417
438
|
}
|
|
418
439
|
const path = kind === 'groups' ? '/api/me/im-delegations/groups'
|
|
419
440
|
: kind === 'dm-chat' ? '/api/me/im-delegations/dm-chat'
|
|
441
|
+
: kind === 'challenge' ? '/api/me/im-delegations/owner-challenge'
|
|
420
442
|
: request.method === 'DELETE'
|
|
421
443
|
? `/api/me/im-delegations/bots/${encodeURIComponent(body.bot_id)}`
|
|
422
444
|
: '/api/me/im-delegations/bots'
|
|
@@ -430,6 +452,7 @@ async function fetchDelegationGroupSettings(request, ctx, credentials, settings,
|
|
|
430
452
|
method: request.method,
|
|
431
453
|
headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json',
|
|
432
454
|
...(request.method !== 'GET' ? { origin: new URL(connection.serviceUrl).origin } : {}),
|
|
455
|
+
...(kind === 'challenge' ? { 'x-ant-owner-approval-version': '1' } : {}),
|
|
433
456
|
...(['POST', 'PUT'].includes(request.method) ? { 'content-type': 'application/json' } : {}) },
|
|
434
457
|
...(['POST', 'PUT'].includes(request.method) ? { body: JSON.stringify(body) } : {}),
|
|
435
458
|
redirect: 'manual', signal: AbortSignal.timeout(12_000),
|
|
@@ -448,6 +471,16 @@ async function fetchDelegationGroupSettings(request, ctx, credentials, settings,
|
|
|
448
471
|
}
|
|
449
472
|
const text = await readLimitedBody(response)
|
|
450
473
|
if (text === null) return jsonResponse(502, { message: '团队服务响应过大。' })
|
|
474
|
+
if (kind === 'challenge' && request.method === 'POST' && response.ok) {
|
|
475
|
+
let challenge
|
|
476
|
+
try { challenge = JSON.parse(text) } catch {
|
|
477
|
+
return jsonResponse(502, { message: '团队服务返回的绑定码格式无效。' })
|
|
478
|
+
}
|
|
479
|
+
const host = getHost?.()
|
|
480
|
+
if (!host?.rememberOwnerChallenge?.(body.bot_fingerprint, challenge?.code)) {
|
|
481
|
+
return jsonResponse(503, { message: '本机协作收件尚未就绪,请稍后刷新后重新生成绑定码。' })
|
|
482
|
+
}
|
|
483
|
+
}
|
|
451
484
|
if (kind === 'groups' && request.method === 'GET' && response.ok) {
|
|
452
485
|
try {
|
|
453
486
|
const groups = JSON.parse(text)
|
|
@@ -563,9 +596,10 @@ async function fetchDelegationCards(request, ctx, credentials, settings) {
|
|
|
563
596
|
async function fetchDelegationRuleRecognition(request, credentials, settings, getHost) {
|
|
564
597
|
if (request.method !== 'POST') return jsonResponse(405, { message: '只支持 POST 请求。' })
|
|
565
598
|
try {
|
|
566
|
-
|
|
599
|
+
request.signal.throwIfAborted()
|
|
600
|
+
const connection = await waitForSignal(readMemberConnection(credentials, settings), request.signal)
|
|
567
601
|
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
568
|
-
const raw = await request.text()
|
|
602
|
+
const raw = await waitForSignal(request.text(), request.signal)
|
|
569
603
|
if (raw.length > 8_192) return jsonResponse(413, { message: '规则描述过长。' })
|
|
570
604
|
let body
|
|
571
605
|
try { body = JSON.parse(raw) } catch { return jsonResponse(400, { message: '规则识别请求格式无效。' }) }
|
|
@@ -574,7 +608,7 @@ async function fetchDelegationRuleRecognition(request, credentials, settings, ge
|
|
|
574
608
|
}
|
|
575
609
|
const host = getHost?.()
|
|
576
610
|
if (!host?.recognizeRule) return jsonResponse(503, { message: '本机 DSH 协作会话尚未就绪,请稍后重试。' })
|
|
577
|
-
return jsonResponse(200, await host.recognizeRule(body.description))
|
|
611
|
+
return jsonResponse(200, await host.recognizeRule(body.description, request.signal))
|
|
578
612
|
} catch (error) {
|
|
579
613
|
return jsonResponse(502, { message: error?.message || '任务规则识别失败,请稍后重试。' })
|
|
580
614
|
}
|
|
@@ -602,12 +636,14 @@ async function fetchDelegationExecutors(request, ctx) {
|
|
|
602
636
|
if (Array.isArray(listed)) providers = listed
|
|
603
637
|
} catch {}
|
|
604
638
|
const available = new Set(providers)
|
|
605
|
-
const
|
|
639
|
+
const providerReason = (name) => `DSH 尚未启用 ${name} 子 Agent 提供方。`
|
|
606
640
|
return jsonResponse(200, [
|
|
607
641
|
{ id: 'dsh', title: 'DSH', available: Boolean(optionalHostService(ctx, 'sessionController')
|
|
608
642
|
&& optionalHostService(ctx, 'agents')) },
|
|
609
|
-
{ id: 'codex', title: 'Codex', available:
|
|
610
|
-
|
|
643
|
+
{ id: 'codex', title: 'Codex', available: available.has('codex'),
|
|
644
|
+
...(!available.has('codex') ? { reason: providerReason('Codex') } : {}) },
|
|
645
|
+
{ id: 'claude-code', title: 'Claude Code', available: available.has('claude-code'),
|
|
646
|
+
...(!available.has('claude-code') ? { reason: providerReason('Claude Code') } : {}) },
|
|
611
647
|
{ id: 'acp', title: 'DSH ACP', available: available.has('acp') },
|
|
612
648
|
{ id: 'dsh-sdk', title: 'DSH SDK 子代理', available: available.has('dsh-sdk') },
|
|
613
649
|
])
|
|
@@ -1161,6 +1197,7 @@ export function apply(ctx) {
|
|
|
1161
1197
|
[DELEGATION_ENROLLED_BOTS_PATH, ['GET', 'POST', 'DELETE'], 'bots'],
|
|
1162
1198
|
[DELEGATION_GROUPS_PATH, ['GET', 'PUT'], 'groups'],
|
|
1163
1199
|
[DELEGATION_DM_CHAT_PATH, ['PUT'], 'dm-chat'],
|
|
1200
|
+
[DELEGATION_OWNER_CHALLENGE_PATH, ['GET', 'POST', 'DELETE'], 'challenge'],
|
|
1164
1201
|
]) {
|
|
1165
1202
|
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
1166
1203
|
path, methods, requestBody: 'buffered',
|