@ai-wendao/ant 0.4.0 → 0.4.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/README.md +5 -3
- package/client.js +504 -18
- package/conversation.js +658 -0
- package/cordis.patch.yml +13 -0
- package/delegation.js +425 -37
- package/index.js +146 -5
- package/package.json +2 -2
package/index.js
CHANGED
|
@@ -3,7 +3,8 @@ export const name = 'ant'
|
|
|
3
3
|
import { createHash } from 'node:crypto'
|
|
4
4
|
import { createRequire } from 'node:module'
|
|
5
5
|
import { installSkill, listSkills, uninstallSkill } from './skill-install.js'
|
|
6
|
-
import { recentDelegationStatus, startDelegationHost
|
|
6
|
+
import { readLocalDelegationSettings, recentDelegationStatus, startDelegationHost,
|
|
7
|
+
writeLocalDelegationSettings } from './delegation.js'
|
|
7
8
|
|
|
8
9
|
export const inject = []
|
|
9
10
|
|
|
@@ -25,6 +26,11 @@ const DELEGATION_ENROLLED_BOTS_PATH = '/api/ant-teams/delegation/enrolled-bots'
|
|
|
25
26
|
const DELEGATION_GROUPS_PATH = '/api/ant-teams/delegation/groups'
|
|
26
27
|
const DELEGATION_OWNER_CHALLENGE_PATH = '/api/ant-teams/delegation/owner-challenge'
|
|
27
28
|
const DELEGATION_STATUS_PATH = '/api/ant-teams/delegation/status'
|
|
29
|
+
const DELEGATION_CARDS_PATH = '/api/ant-teams/delegation/cards'
|
|
30
|
+
const DELEGATION_SETTINGS_PATH = '/api/ant-teams/delegation/settings'
|
|
31
|
+
const DELEGATION_EXECUTORS_PATH = '/api/ant-teams/delegation/executors'
|
|
32
|
+
const DELEGATION_LOCAL_SETTINGS_PATH = '/api/ant-teams/delegation/local-settings'
|
|
33
|
+
const DELEGATION_CANCEL_PATH = '/api/ant-teams/delegation/cancel'
|
|
28
34
|
const ANT_NPM_PACKAGE_NAME = '@ai-wendao/ant'
|
|
29
35
|
const BUNDLE_VERSION = createRequire(import.meta.url)('./package.json').version
|
|
30
36
|
const MAX_MODEL_RESPONSE_BYTES = 1024 * 1024
|
|
@@ -124,7 +130,7 @@ async function updateModelSession(serviceUrl, token, action) {
|
|
|
124
130
|
})
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
async function readLimitedBody(response) {
|
|
133
|
+
async function readLimitedBody(response, maxBytes = MAX_MODEL_RESPONSE_BYTES) {
|
|
128
134
|
if (!response.body) return ''
|
|
129
135
|
const reader = response.body.getReader()
|
|
130
136
|
const chunks = []
|
|
@@ -134,7 +140,7 @@ async function readLimitedBody(response) {
|
|
|
134
140
|
const { done, value } = await reader.read()
|
|
135
141
|
if (done) break
|
|
136
142
|
size += value.byteLength
|
|
137
|
-
if (size >
|
|
143
|
+
if (size > maxBytes) {
|
|
138
144
|
await reader.cancel()
|
|
139
145
|
return null
|
|
140
146
|
}
|
|
@@ -210,6 +216,7 @@ async function fetchDelegationBots(request, ctx) {
|
|
|
210
216
|
connected: details.connected === true,
|
|
211
217
|
available: details.capabilities?.includes('exclusive-text-consumer')
|
|
212
218
|
&& details.capabilities?.includes('reply-text-checked'),
|
|
219
|
+
history_available: details.capabilities?.includes('history-text-checked') === true,
|
|
213
220
|
}
|
|
214
221
|
} catch { return null }
|
|
215
222
|
}))
|
|
@@ -331,6 +338,111 @@ async function fetchDelegationStatus(request, credentials, settings) {
|
|
|
331
338
|
} catch { return jsonResponse(503, { message: '本机委托任务记录暂时无法读取,请联系管理员检查。' }) }
|
|
332
339
|
}
|
|
333
340
|
|
|
341
|
+
async function fetchDelegationCards(request, ctx, credentials, settings) {
|
|
342
|
+
if (!['GET', 'POST', 'DELETE'].includes(request.method)) return jsonResponse(405, { message: '请求方式不支持。' })
|
|
343
|
+
let connection
|
|
344
|
+
try { connection = await readMemberConnection(credentials, settings) } catch {
|
|
345
|
+
return jsonResponse(500, { message: '无法读取 ANT 连接。' })
|
|
346
|
+
}
|
|
347
|
+
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
348
|
+
let body = null
|
|
349
|
+
if (request.method !== 'GET') {
|
|
350
|
+
try {
|
|
351
|
+
const raw = await request.text()
|
|
352
|
+
if (raw.length > 32_768) return jsonResponse(413, { message: '任务设置过大。' })
|
|
353
|
+
body = JSON.parse(raw)
|
|
354
|
+
} catch { return jsonResponse(400, { message: '任务设置格式无效。' }) }
|
|
355
|
+
}
|
|
356
|
+
if (request.method === 'POST') {
|
|
357
|
+
const service = dshImService(ctx)
|
|
358
|
+
if (!service?.describeBot) return jsonResponse(503, { message: '请先安装并启用 DSH-IM。' })
|
|
359
|
+
try {
|
|
360
|
+
const bot = await service.describeBot(body.bot_id)
|
|
361
|
+
if (bot.channel !== 'feishu' || !bot.connected || bot.account?.fingerprint !== body.bot_fingerprint
|
|
362
|
+
|| !bot.capabilities?.includes('exclusive-text-consumer') || !bot.capabilities?.includes('reply-text-checked')) {
|
|
363
|
+
return jsonResponse(400, { message: '请选择已连接且支持协作收件的飞书机器人。' })
|
|
364
|
+
}
|
|
365
|
+
} catch { return jsonResponse(400, { message: '机器人当前不可用。' }) }
|
|
366
|
+
}
|
|
367
|
+
if (request.method === 'DELETE' && (typeof body?.id !== 'string' || !/^[0-9a-f-]{36}$/iu.test(body.id))) {
|
|
368
|
+
return jsonResponse(400, { message: '任务编号无效。' })
|
|
369
|
+
}
|
|
370
|
+
const path = request.method === 'DELETE'
|
|
371
|
+
? `/api/me/im-delegations/cards/${encodeURIComponent(body.id)}` : '/api/me/im-delegations/cards'
|
|
372
|
+
try {
|
|
373
|
+
const response = await fetch(new URL(path, connection.serviceUrl), {
|
|
374
|
+
method: request.method,
|
|
375
|
+
headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json',
|
|
376
|
+
...(request.method === 'POST' ? { 'content-type': 'application/json' } : {}) },
|
|
377
|
+
...(request.method === 'POST' ? { body: JSON.stringify(body) } : {}),
|
|
378
|
+
redirect: 'manual', signal: AbortSignal.timeout(12_000),
|
|
379
|
+
})
|
|
380
|
+
if (response.status === 404 && request.method !== 'DELETE') return jsonResponse(426, { message: '团队服务端尚未支持自定义任务,请联系管理员升级。' })
|
|
381
|
+
if (response.status === 204) return new Response(null, { status: 204 })
|
|
382
|
+
const text = await readLimitedBody(response, request.method === 'GET' ? 8 * 1024 * 1024 : MAX_MODEL_RESPONSE_BYTES)
|
|
383
|
+
if (text === null) return jsonResponse(502, { message: '团队服务响应过大。' })
|
|
384
|
+
return new Response(text, { status: response.status,
|
|
385
|
+
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' } })
|
|
386
|
+
} catch { return jsonResponse(502, { message: '暂时无法连接 ANT 团队服务。' }) }
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function fetchDelegationRuntimeSettings(request, credentials, settings) {
|
|
390
|
+
if (request.method !== 'GET') return jsonResponse(405, { message: '请求方式不支持。' })
|
|
391
|
+
try {
|
|
392
|
+
const connection = await readMemberConnection(credentials, settings)
|
|
393
|
+
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
394
|
+
const response = await fetch(new URL('/api/me/im-delegations/settings', connection.serviceUrl), {
|
|
395
|
+
headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json' },
|
|
396
|
+
redirect: 'manual', signal: AbortSignal.timeout(12_000),
|
|
397
|
+
})
|
|
398
|
+
if (!response.ok) return jsonResponse(response.status, { message: '暂时无法读取团队协作设置。' })
|
|
399
|
+
return jsonResponse(200, await response.json())
|
|
400
|
+
} catch { return jsonResponse(502, { message: '暂时无法读取团队协作设置。' }) }
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function fetchDelegationExecutors(request, ctx) {
|
|
404
|
+
if (request.method !== 'GET') return jsonResponse(405, { message: '请求方式不支持。' })
|
|
405
|
+
let providers = []
|
|
406
|
+
try { providers = (ctx.get?.('subagents') ?? ctx.subagents)?.list?.() || [] } catch {}
|
|
407
|
+
const available = new Set(providers)
|
|
408
|
+
return jsonResponse(200, [
|
|
409
|
+
{ id: 'dsh', title: 'DSH', available: Boolean(ctx.sessionController && ctx.agents) },
|
|
410
|
+
{ id: 'codex', title: 'Codex', available: available.has('codex') },
|
|
411
|
+
{ id: 'claude-code', title: 'Claude Code', available: available.has('claude-code') },
|
|
412
|
+
{ id: 'acp', title: 'DSH ACP', available: available.has('acp') },
|
|
413
|
+
{ id: 'dsh-sdk', title: 'DSH SDK 子代理', available: available.has('dsh-sdk') },
|
|
414
|
+
])
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
async function fetchDelegationLocalSettings(request, credentials, settings) {
|
|
418
|
+
if (!['GET', 'PUT'].includes(request.method)) return jsonResponse(405, { message: '请求方式不支持。' })
|
|
419
|
+
try {
|
|
420
|
+
if (!await readMemberConnection(credentials, settings)) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
421
|
+
if (request.method === 'GET') return jsonResponse(200, await readLocalDelegationSettings())
|
|
422
|
+
const raw = await request.text()
|
|
423
|
+
if (raw.length > 256) return jsonResponse(413, { message: '设置内容过大。' })
|
|
424
|
+
const body = JSON.parse(raw)
|
|
425
|
+
return jsonResponse(200, await writeLocalDelegationSettings(body))
|
|
426
|
+
} catch (error) { return jsonResponse(400, { message: error?.message || '本机设置无法保存。' }) }
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
async function fetchDelegationCancel(request, credentials, settings, getHost) {
|
|
430
|
+
if (request.method !== 'POST') return jsonResponse(405, { message: '请求方式不支持。' })
|
|
431
|
+
try {
|
|
432
|
+
const connection = await readMemberConnection(credentials, settings)
|
|
433
|
+
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
434
|
+
const raw = await request.text()
|
|
435
|
+
if (raw.length > 256) return jsonResponse(413, { message: '请求内容过大。' })
|
|
436
|
+
const body = JSON.parse(raw)
|
|
437
|
+
if (typeof body.task_id !== 'string' || !/^[A-F0-9]{10}$/u.test(body.task_id)) {
|
|
438
|
+
return jsonResponse(400, { message: '任务编号无效。' })
|
|
439
|
+
}
|
|
440
|
+
const host = getHost()
|
|
441
|
+
if (!host) return jsonResponse(503, { message: '协作机器人尚未就绪。' })
|
|
442
|
+
return jsonResponse(200, { canceled: await host.cancelTask(body.task_id, connection.serviceUrl) })
|
|
443
|
+
} catch { return jsonResponse(503, { message: '暂时无法取消任务,请稍后重试。' }) }
|
|
444
|
+
}
|
|
445
|
+
|
|
334
446
|
async function fetchServiceInfo(request, credentials, settings) {
|
|
335
447
|
if (request.method !== 'POST') return jsonResponse(405, { message: '只支持 POST 请求' })
|
|
336
448
|
let body
|
|
@@ -735,6 +847,7 @@ async function fetchAuthRequest(request, endpoint, credentials, settings) {
|
|
|
735
847
|
|
|
736
848
|
export function apply(ctx) {
|
|
737
849
|
ctx.inject(['connection', 'credentials', 'settings'], (connectionCtx) => {
|
|
850
|
+
let delegationHost = null
|
|
738
851
|
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
739
852
|
path: SERVICE_INFO_PATH,
|
|
740
853
|
methods: ['POST'],
|
|
@@ -803,6 +916,27 @@ export function apply(ctx) {
|
|
|
803
916
|
path: DELEGATION_STATUS_PATH, methods: ['GET'], requestBody: 'buffered',
|
|
804
917
|
fetch: (request) => fetchDelegationStatus(request, connectionCtx.credentials, connectionCtx.settings),
|
|
805
918
|
}), 'ant-teams: local delegated task status')
|
|
919
|
+
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
920
|
+
path: DELEGATION_CARDS_PATH, methods: ['GET', 'POST', 'DELETE'], requestBody: 'buffered',
|
|
921
|
+
fetch: (request) => fetchDelegationCards(request, connectionCtx, connectionCtx.credentials, connectionCtx.settings),
|
|
922
|
+
}), 'ant-teams: member task cards')
|
|
923
|
+
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
924
|
+
path: DELEGATION_SETTINGS_PATH, methods: ['GET'], requestBody: 'buffered',
|
|
925
|
+
fetch: (request) => fetchDelegationRuntimeSettings(request, connectionCtx.credentials, connectionCtx.settings),
|
|
926
|
+
}), 'ant-teams: collaboration defaults')
|
|
927
|
+
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
928
|
+
path: DELEGATION_EXECUTORS_PATH, methods: ['GET'], requestBody: 'buffered',
|
|
929
|
+
fetch: (request) => fetchDelegationExecutors(request, connectionCtx),
|
|
930
|
+
}), 'ant-teams: local executor availability')
|
|
931
|
+
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
932
|
+
path: DELEGATION_LOCAL_SETTINGS_PATH, methods: ['GET', 'PUT'], requestBody: 'buffered',
|
|
933
|
+
fetch: (request) => fetchDelegationLocalSettings(request, connectionCtx.credentials, connectionCtx.settings),
|
|
934
|
+
}), 'ant-teams: local delegated-task concurrency')
|
|
935
|
+
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
936
|
+
path: DELEGATION_CANCEL_PATH, methods: ['POST'], requestBody: 'buffered',
|
|
937
|
+
fetch: (request) => fetchDelegationCancel(request, connectionCtx.credentials,
|
|
938
|
+
connectionCtx.settings, () => delegationHost),
|
|
939
|
+
}), 'ant-teams: owner cancellation for delegated tasks')
|
|
806
940
|
connectionCtx.effect(() => connectionCtx.connection.fetch.register({
|
|
807
941
|
path: DISCONNECT_PATH,
|
|
808
942
|
methods: ['POST'],
|
|
@@ -848,8 +982,15 @@ export function apply(ctx) {
|
|
|
848
982
|
}
|
|
849
983
|
}, 'ant-teams: ANT model activity session')
|
|
850
984
|
connectionCtx.inject?.(['dshIm', 'sessionController', 'sessions', 'agents', 'tools'], (delegationCtx) => {
|
|
851
|
-
delegationCtx.effect(() =>
|
|
852
|
-
|
|
985
|
+
delegationCtx.effect(() => {
|
|
986
|
+
const host = startDelegationHost(delegationCtx,
|
|
987
|
+
() => readMemberConnection(delegationCtx.credentials, delegationCtx.settings))
|
|
988
|
+
delegationHost = host
|
|
989
|
+
return async () => {
|
|
990
|
+
if (delegationHost === host) delegationHost = null
|
|
991
|
+
await host()
|
|
992
|
+
}
|
|
993
|
+
},
|
|
853
994
|
'ant-teams: delegated IM review intake')
|
|
854
995
|
})
|
|
855
996
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-wendao/ant",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "ANT (AI-native Teams) connects a DeepSeek Harness Desktop profile to team identity and approved models.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"./client": "./client.js",
|
|
17
17
|
"./locale/*.json": "./locale/*.json"
|
|
18
18
|
},
|
|
19
|
-
"files": ["index.js", "client.js", "skill-install.js", "delegation.js", "cordis.patch.yml", "locale/*.json", "tools/migrate-legacy.mjs", "MIGRATION.md", "README.md"],
|
|
19
|
+
"files": ["index.js", "client.js", "skill-install.js", "delegation.js", "conversation.js", "cordis.patch.yml", "locale/*.json", "tools/migrate-legacy.mjs", "MIGRATION.md", "README.md"],
|
|
20
20
|
"dsh": {
|
|
21
21
|
"bundle": {
|
|
22
22
|
"patch": "./cordis.patch.yml"
|