@whyshu/argent 0.2.6 → 0.2.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whyshu/argent",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "Argent 单 bundle(dsh web / DSH Desktop 同一插件):ERP 连接器 + 问述代理 + 登录/续期 + MCP 网关 + 伞伞桌宠(含积分)",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -227,39 +227,44 @@ export function apply(ctx) {
227
227
  }
228
228
  }
229
229
 
230
- // MCP 网关(engine.* / erp.* / ml.*)
231
- try {
232
- const mcpClient = await hostImport('@deepseek-ai/dsh-mcp-client')
233
- const mcpReady = ctx.plugin(mcpClient, {
234
- transport: 'stdio',
235
- serverName: 'argent',
236
- command: process.execPath,
237
- args: [join(PKG_ROOT, 'mcp', 'gateway.mjs')],
238
- cwd: PKG_ROOT,
239
- env: {
240
- ARGENT_DATA_DIR: dataDir,
241
- ARGENT_TENANT: TENANT,
242
- ARGENT_ENGINE_DIR: engineDir,
243
- ARGENT_GATEWAY_ML: process.env.ARGENT_GATEWAY_ML || '',
244
- },
245
- toolCallTimeoutMs: 180000,
246
- failOnStartupError: false,
247
- })
248
- // 启动等待上限:网关子进程已起但 mcp-client 握手可能很慢(2026-11-07 本机实测挂起)
249
- // ⇒ 超时只告警、不阻塞后续(隧道/ERP 连接器已在前面启动)。
250
- const MCP_START_TIMEOUT_MS = 20_000
251
- const raced = await Promise.race([
252
- mcpReady.then(() => 'ok'),
253
- new Promise((resolve) => {
254
- const t = setTimeout(() => resolve('timeout'), MCP_START_TIMEOUT_MS)
255
- t.unref?.()
256
- }),
257
- ])
258
- if (raced === 'ok') console.log(`[argent] MCP 网关已注册(engineDir=${engineDir || '(无引擎)'})`)
259
- else console.warn(`[argent] MCP 网关握手超时(${MCP_START_TIMEOUT_MS}ms,后台继续;不影响隧道/ERP 连接器)`)
260
- } catch (e) {
261
- console.error('[argent] MCP 网关注册失败(其余功能不受影响):', e?.message || e)
262
- }
230
+ // ⛔ 2026-11-07 实测:启动阶段 ctx.plugin(dsh-mcp-client) 会挂起 dsh 启动(端口 bound 但 HTTP 不响应),
231
+ // 用户侧表现为「dsh 启动失败」;只有删插件才能启动。故:默认延后注册,且可用 ARGENT_MCP_DISABLE=1 关闭。
232
+ if (process.env.ARGENT_MCP_DISABLE === '1') {
233
+ console.log('[argent] MCP 网关已禁用(ARGENT_MCP_DISABLE=1)')
234
+ } else setTimeout(() => { void (async () => {
235
+ try {
236
+ const mcpClient = await hostImport('@deepseek-ai/dsh-mcp-client')
237
+ const mcpReady = ctx.plugin(mcpClient, {
238
+ transport: 'stdio',
239
+ serverName: 'argent',
240
+ command: process.execPath,
241
+ args: [join(PKG_ROOT, 'mcp', 'gateway.mjs')],
242
+ cwd: PKG_ROOT,
243
+ env: {
244
+ ARGENT_DATA_DIR: dataDir,
245
+ ARGENT_TENANT: TENANT,
246
+ ARGENT_ENGINE_DIR: engineDir,
247
+ ARGENT_GATEWAY_ML: process.env.ARGENT_GATEWAY_ML || '',
248
+ },
249
+ toolCallTimeoutMs: 180000,
250
+ failOnStartupError: false,
251
+ })
252
+ // 启动等待上限:网关子进程已起但 mcp-client 握手可能很慢(2026-11-07 本机实测挂起)
253
+ // ⇒ 超时只告警、不阻塞后续(隧道/ERP 连接器已在前面启动)。
254
+ const MCP_START_TIMEOUT_MS = 20_000
255
+ const raced = await Promise.race([
256
+ mcpReady.then(() => 'ok'),
257
+ new Promise((resolve) => {
258
+ const t = setTimeout(() => resolve('timeout'), MCP_START_TIMEOUT_MS)
259
+ t.unref?.()
260
+ }),
261
+ ])
262
+ if (raced === 'ok') console.log(`[argent] MCP 网关已注册(engineDir=${engineDir || '(无引擎)'})`)
263
+ else console.warn(`[argent] MCP 网关握手超时(${MCP_START_TIMEOUT_MS}ms,后台继续;不影响隧道/ERP 连接器)`)
264
+ } catch (e) {
265
+ console.error('[argent] MCP 网关注册失败(其余功能不受影响):', e?.message || e)
266
+ }
267
+ })(); }, 5000)
263
268
 
264
269
  // ERP 连接器:只有 poller 才启动(UI 端不抢队列)
265
270
  if (role === 'poller') {
package/src/tunnel.mjs CHANGED
@@ -530,18 +530,33 @@ export function startTunnel(options = {}) {
530
530
  }
531
531
 
532
532
  // ── dsh 准入 cookie(仅内存;401/403 重换一次)──────────────────────────
533
+ // dsh 准入 token 的三条来源(优先级:env → 启动脚本写出的 token 文件 → 本机 /api/argent-state/access)
534
+ // 为什么需要文件来源:`/api/argent-state/access` 由 argent-core 插件提供;单插件(@whyshu/argent)装配下
535
+ // 该端点 401 ⇒ 隧道拿不到 token ⇒ App 侧表现为 access-unavailable(2026-11-07 实测)。
536
+ const readTokenFile = () => {
537
+ try {
538
+ const t = readFileSync(join(String(options.dataDir || ''), 'dsh-web.token'), 'utf8').trim()
539
+ return t || ''
540
+ } catch { return '' }
541
+ }
533
542
  const acquireCookie = async ({ refresh = false } = {}) => {
534
543
  if (!refresh && dsh.cookie) return dsh.cookie
535
- let access
536
- try {
537
- access = await fetchImpl(`${dshBase}${DSH_ACCESS_PATH}`, {
538
- headers: { accept: 'application/json' },
539
- signal: AbortSignal.timeout(5000),
540
- })
541
- } catch { throw err('access-unreachable') }
542
544
  let body = null
543
- try { body = await access.json() } catch { body = null }
544
- if (!access.ok || !body || body.ok !== true || !body.token) throw err('access-unavailable', `HTTP ${access.status}`)
545
+ const envToken = String(env.ARGENT_DSH_TOKEN || '').trim()
546
+ const fileToken = envToken ? '' : readTokenFile()
547
+ if (envToken || fileToken) {
548
+ body = { ok: true, token: envToken || fileToken }
549
+ } else {
550
+ let access
551
+ try {
552
+ access = await fetchImpl(`${dshBase}${DSH_ACCESS_PATH}`, {
553
+ headers: { accept: 'application/json' },
554
+ signal: AbortSignal.timeout(5000),
555
+ })
556
+ } catch { throw err('access-unreachable') }
557
+ try { body = await access.json() } catch { body = null }
558
+ if (!access.ok || !body || body.ok !== true || !body.token) throw err('access-unavailable', `HTTP ${access.status}`)
559
+ }
545
560
  let res
546
561
  try {
547
562
  res = await fetchImpl(`${dshBase}/?token=${encodeURIComponent(String(body.token))}`, {