@ai-wendao/ant 0.4.1 → 0.4.4

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/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export const name = 'ant'
2
2
 
3
3
  import { createHash } from 'node:crypto'
4
+ import { spawn } from 'node:child_process'
4
5
  import { createRequire } from 'node:module'
5
6
  import { installSkill, listSkills, uninstallSkill } from './skill-install.js'
6
7
  import { readLocalDelegationSettings, recentDelegationStatus, startDelegationHost,
@@ -201,6 +202,10 @@ function dshImService(ctx) {
201
202
  try { return ctx.get?.('dshIm') ?? ctx.dshIm ?? null } catch { return null }
202
203
  }
203
204
 
205
+ function optionalHostService(ctx, name) {
206
+ try { return ctx.get?.(name) ?? ctx[name] ?? null } catch { return null }
207
+ }
208
+
204
209
  async function fetchDelegationBots(request, ctx) {
205
210
  if (request.method !== 'GET') return jsonResponse(405, { message: '只支持 GET 请求。' })
206
211
  const service = dshImService(ctx)
@@ -259,6 +264,7 @@ async function fetchDelegationGrants(request, ctx, credentials, settings) {
259
264
  const response = await fetch(new URL(path, connection.serviceUrl), {
260
265
  method: request.method,
261
266
  headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json',
267
+ ...(request.method !== 'GET' ? { origin: new URL(connection.serviceUrl).origin } : {}),
262
268
  ...(request.method === 'POST' ? { 'content-type': 'application/json' } : {}) },
263
269
  ...(request.method === 'POST' ? { body: JSON.stringify(body) } : {}),
264
270
  redirect: 'manual', signal: AbortSignal.timeout(12_000),
@@ -274,8 +280,8 @@ async function fetchDelegationGrants(request, ctx, credentials, settings) {
274
280
  } catch { return jsonResponse(502, { message: '暂时无法连接 ANT 团队服务。' }) }
275
281
  }
276
282
 
277
- async function fetchDelegationGroupSettings(request, ctx, credentials, settings, kind) {
278
- const methods = kind === 'groups' ? ['GET'] : kind === 'challenge' ? ['POST'] : ['GET', 'POST', 'DELETE']
283
+ async function fetchDelegationGroupSettings(request, ctx, credentials, settings, kind, getHost) {
284
+ const methods = kind === 'groups' ? ['GET', 'PUT'] : kind === 'challenge' ? ['POST'] : ['GET', 'POST', 'DELETE']
279
285
  if (!methods.includes(request.method)) return jsonResponse(405, { message: '请求方式不支持。' })
280
286
  let connection
281
287
  try { connection = await readMemberConnection(credentials, settings) } catch {
@@ -311,17 +317,29 @@ async function fetchDelegationGroupSettings(request, ctx, credentials, settings,
311
317
  ? `/api/me/im-delegations/bots/${encodeURIComponent(body.bot_id)}`
312
318
  : '/api/me/im-delegations/bots'
313
319
  try {
314
- const response = await fetch(new URL(path, connection.serviceUrl), {
320
+ const destination = new URL(path, connection.serviceUrl)
321
+ if (kind === 'bots' && request.method === 'GET'
322
+ && request.headers.get('x-ant-include-unbound') === 'true') {
323
+ destination.searchParams.set('include_unbound', 'true')
324
+ }
325
+ const response = await fetch(destination, {
315
326
  method: request.method,
316
327
  headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json',
317
- ...(request.method === 'POST' ? { 'content-type': 'application/json' } : {}) },
318
- ...(request.method === 'POST' ? { body: JSON.stringify(body) } : {}),
328
+ ...(request.method !== 'GET' ? { origin: new URL(connection.serviceUrl).origin } : {}),
329
+ ...(['POST', 'PUT'].includes(request.method) ? { 'content-type': 'application/json' } : {}) },
330
+ ...(['POST', 'PUT'].includes(request.method) ? { body: JSON.stringify(body) } : {}),
319
331
  redirect: 'manual', signal: AbortSignal.timeout(12_000),
320
332
  })
321
333
  if (response.status === 404 && request.method !== 'DELETE') {
322
334
  return jsonResponse(426, { message: '团队服务端尚未支持群聊委托,请联系管理员升级 ANT 服务端。' })
323
335
  }
324
- if (response.status === 204) return new Response(null, { status: 204 })
336
+ if (response.status === 204) {
337
+ if (kind === 'groups' && request.method === 'PUT') {
338
+ const refresh = getHost?.()?.refresh
339
+ if (refresh) await refresh().catch(() => undefined)
340
+ }
341
+ return new Response(null, { status: 204 })
342
+ }
325
343
  const text = await readLimitedBody(response)
326
344
  if (text === null) return jsonResponse(502, { message: '团队服务响应过大。' })
327
345
  return new Response(text, { status: response.status,
@@ -373,6 +391,7 @@ async function fetchDelegationCards(request, ctx, credentials, settings) {
373
391
  const response = await fetch(new URL(path, connection.serviceUrl), {
374
392
  method: request.method,
375
393
  headers: { authorization: `Bearer ${connection.token}`, accept: 'application/json',
394
+ ...(request.method !== 'GET' ? { origin: new URL(connection.serviceUrl).origin } : {}),
376
395
  ...(request.method === 'POST' ? { 'content-type': 'application/json' } : {}) },
377
396
  ...(request.method === 'POST' ? { body: JSON.stringify(body) } : {}),
378
397
  redirect: 'manual', signal: AbortSignal.timeout(12_000),
@@ -400,15 +419,35 @@ async function fetchDelegationRuntimeSettings(request, credentials, settings) {
400
419
  } catch { return jsonResponse(502, { message: '暂时无法读取团队协作设置。' }) }
401
420
  }
402
421
 
403
- function fetchDelegationExecutors(request, ctx) {
422
+ async function fetchDelegationExecutors(request, ctx) {
404
423
  if (request.method !== 'GET') return jsonResponse(405, { message: '请求方式不支持。' })
405
424
  let providers = []
406
- try { providers = (ctx.get?.('subagents') ?? ctx.subagents)?.list?.() || [] } catch {}
425
+ try {
426
+ const listed = optionalHostService(ctx, 'subagents')?.list?.()
427
+ if (Array.isArray(listed)) providers = listed
428
+ } catch {}
407
429
  const available = new Set(providers)
430
+ const codexCliAvailable = await new Promise((resolve) => {
431
+ const child = spawn('codex', ['exec', '--help'], { stdio: ['ignore', 'pipe', 'ignore'] })
432
+ let help = ''
433
+ child.stdout.on('data', (chunk) => { help = (help + chunk.toString()).slice(0, 32_000) })
434
+ const timer = setTimeout(() => { child.kill(); resolve(false) }, 3_000)
435
+ child.once('error', () => { clearTimeout(timer); resolve(false) })
436
+ child.once('close', (code) => { clearTimeout(timer)
437
+ resolve(code === 0 && ['--ignore-user-config', '--strict-config', '--output-last-message']
438
+ .every((flag) => help.includes(flag))) })
439
+ })
440
+ const nativePrSnapshotSupported = process.platform !== 'win32'
441
+ const nativePrUnavailableReason = nativePrSnapshotSupported ? null
442
+ : '当前 Windows 环境无法限制 Git 仓库缓存容量'
408
443
  return jsonResponse(200, [
409
- { id: 'dsh', title: 'DSH', available: Boolean(ctx.sessionController && ctx.agents) },
444
+ { id: 'dsh', title: 'DSH', available: Boolean(optionalHostService(ctx, 'sessionController')
445
+ && optionalHostService(ctx, 'agents')) },
410
446
  { id: 'codex', title: 'Codex', available: available.has('codex') },
411
- { id: 'claude-code', title: 'Claude Code', available: available.has('claude-code') },
447
+ { id: 'codex-readonly', title: 'Codex 专用只读差异审查', available: codexCliAvailable && nativePrSnapshotSupported,
448
+ ...(nativePrUnavailableReason ? { reason: nativePrUnavailableReason } : {}) },
449
+ { id: 'claude-code', title: 'Claude Code', available: available.has('claude-code') && nativePrSnapshotSupported,
450
+ ...(nativePrUnavailableReason ? { reason: nativePrUnavailableReason } : {}) },
412
451
  { id: 'acp', title: 'DSH ACP', available: available.has('acp') },
413
452
  { id: 'dsh-sdk', title: 'DSH SDK 子代理', available: available.has('dsh-sdk') },
414
453
  ])
@@ -903,13 +942,13 @@ export function apply(ctx) {
903
942
  }), 'ant-teams: member delegation settings')
904
943
  for (const [path, methods, kind] of [
905
944
  [DELEGATION_ENROLLED_BOTS_PATH, ['GET', 'POST', 'DELETE'], 'bots'],
906
- [DELEGATION_GROUPS_PATH, ['GET'], 'groups'],
945
+ [DELEGATION_GROUPS_PATH, ['GET', 'PUT'], 'groups'],
907
946
  [DELEGATION_OWNER_CHALLENGE_PATH, ['POST'], 'challenge'],
908
947
  ]) {
909
948
  connectionCtx.effect(() => connectionCtx.connection.fetch.register({
910
949
  path, methods, requestBody: 'buffered',
911
950
  fetch: (request) => fetchDelegationGroupSettings(request, connectionCtx,
912
- connectionCtx.credentials, connectionCtx.settings, kind),
951
+ connectionCtx.credentials, connectionCtx.settings, kind, () => delegationHost),
913
952
  }), `ant-teams: member delegation ${kind}`)
914
953
  }
915
954
  connectionCtx.effect(() => connectionCtx.connection.fetch.register({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-wendao/ant",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
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": {