dsh-agent-lines 0.3.6 → 0.3.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/CHANGELOG.en.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  English | [中文](CHANGELOG.md)
4
4
 
5
+ ## 0.3.7 (2026-11-09)
6
+
7
+ - Added line_handoff: structured handoff snapshots (JSON/Markdown), no model call.
8
+ - line_status / line_list now expose lifecycle/title/generation/pending/lastActivityAt/oldSessionId.
9
+ - rebind sends a noReply handoff notice to the new line; replace reuses the onboarding message.
10
+ - list --json can feed an external dashboard; added examples/dashboard notes.
11
+ - Tests 33/33 pass.
12
+
5
13
  ## 0.3.6 (2026-11-09)
6
14
 
7
15
  - Added line lifecycle: line_retire, line_rebind, line_create replace:true, line_rename.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  [English](CHANGELOG.en.md) | 中文
4
4
 
5
+ ## 0.3.7 (2026-11-09)
6
+
7
+ - 新增 line_handoff:结构化交接快照(JSON/Markdown),不调用模型。
8
+ - line_status / line_list 增加 lifecycle/title/generation/pending/lastActivityAt/oldSessionId。
9
+ - rebind 后给新线发 noReply 交接通知;replace 复用 onboarding 消息。
10
+ - list --json 可直接喂给外部看板;新增 examples/dashboard 说明。
11
+ - 测试 33/33 通过。
12
+
5
13
  ## 0.3.6 (2026-11-09)
6
14
 
7
15
  - 新增线生命周期:line_retire、line_rebind、line_create replace:true、line_rename。
File without changes
File without changes
File without changes
package/CONTRIBUTING.md CHANGED
File without changes
package/LICENSE CHANGED
File without changes
package/NOTICE CHANGED
File without changes
package/README.en.md CHANGED
@@ -36,7 +36,7 @@ The script picks the DSH Web profile, installs the plugin, and verifies agent-li
36
36
 
37
37
  Offline or when npm is unavailable, use the local tarball:
38
38
 
39
- bash install.sh ./dsh-agent-lines-0.3.6.tgz
39
+ bash install.sh ./dsh-agent-lines-0.3.7.tgz
40
40
 
41
41
  After install and restart, it works without a config. When you want a fixed manager/worker setup, paste the "Manager config" block below into the file printed by the installer.
42
42
 
@@ -138,6 +138,7 @@ Tools:
138
138
  | `line_claim_manager` | Bind this live root Session as manager; requires `allowClaim: true` and `confirm: "bind-manager"`; global, no shell needed |
139
139
  | `line_list` | List lines, status, unread counts, current line and role |
140
140
  | `line_create` | Manager only: create a line; same label is idempotent; replace:true swaps the label to a fresh Session |
141
+ | `line_handoff` | Manager only: structured handoff snapshot (JSON/Markdown), no model call |
141
142
  | `line_retire` | Manager only: soft-retire; reject new sends, keep Session and history |
142
143
  | `line_rebind` | Manager only: atomically switch a line to a new live Session, optionally migrating backlog |
143
144
  | `line_rename` | Manager only: rename the sidebar title and persist it in lines.db |
package/README.md CHANGED
@@ -36,7 +36,7 @@ DSH 的 super agent 平替插件。
36
36
 
37
37
  离线或 npm 不可用时,用本地 tarball:
38
38
 
39
- bash install.sh ./dsh-agent-lines-0.3.6.tgz
39
+ bash install.sh ./dsh-agent-lines-0.3.7.tgz
40
40
 
41
41
  安装并重启后,不写配置也可以直接使用;需要固定管理线/worker 时,再把下面“管理线配置”粘贴到脚本打印的配置文件。
42
42
 
@@ -138,6 +138,7 @@ line_create({ label: "ops", role: "运维" })
138
138
  | `line_claim_manager` | 把当前 live 根 Session 绑成 manager;需要 `allowClaim: true` 和 `confirm: "bind-manager"`;全局工具,不需要 shell |
139
139
  | `line_list` | 列出线、状态、未读数、当前线和 role |
140
140
  | `line_create` | 仅管理线:创建新线;同 label 幂等;传 replace:true 可给同 label 换新 Session |
141
+ | `line_handoff` | 仅管理线:生成结构化交接单(JSON/Markdown),不调模型 |
141
142
  | `line_retire` | 仅管理线:软下线;拒绝新发送,保留 Session/历史 |
142
143
  | `line_rebind` | 仅管理线:把线原子切到新的 live Session,可迁移积压 |
143
144
  | `line_rename` | 仅管理线:改侧栏标题,持久化到 lines.db |
package/SECURITY.en.md CHANGED
File without changes
package/SECURITY.md CHANGED
File without changes
File without changes
package/cordis.patch.yml CHANGED
File without changes
File without changes
File without changes
package/docs/DEPLOY.en.md CHANGED
File without changes
package/docs/DEPLOY.md CHANGED
File without changes
@@ -103,6 +103,7 @@ The new line is an ordinary DSH Session in the same DSH process; no OS process,
103
103
  line_retire({ line, reason? })
104
104
  line_rebind({ line, sessionId, migrate?: "queued" | "none", reason? })
105
105
  line_create({ label, replace: true, force?, migrate?, title?, reason? })
106
+ line_handoff({ line, format?: "md" | "json", limit?: number })
106
107
  line_rename({ line, title })
107
108
 
108
109
  - retired: line_send returns LINE_RETIRED; the Session and history are kept.
package/docs/PROTOCOL.md CHANGED
@@ -95,6 +95,7 @@ line_move_workspace({ line, workspace }) 把已有线 Session 挂到已有工作
95
95
  line_retire({ line, reason? })
96
96
  line_rebind({ line, sessionId, migrate?: "queued" | "none", reason? })
97
97
  line_create({ label, replace: true, force?, migrate?, title?, reason? })
98
+ line_handoff({ line, format?: "md" | "json", limit?: number })
98
99
  line_rename({ line, title })
99
100
 
100
101
  - retired:line_send 返回 LINE_RETIRED;Session 和消息历史保留。
File without changes
package/docs/SECURITY.md CHANGED
File without changes
File without changes
File without changes
@@ -43,7 +43,7 @@ footer{padding:34px 0 48px;color:var(--muted);font-size:12px}
43
43
  <div class="wrap">
44
44
  <header>
45
45
  <a class="brand" href="../"><span class="mark"></span>dsh-agent-lines</a>
46
- <nav><a href="../">中文</a><a href="https://github.com/Lencen/dsh-agent-lines">GitHub</a><a href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.6">Release</a></nav>
46
+ <nav><a href="../">中文</a><a href="https://github.com/Lencen/dsh-agent-lines">GitHub</a><a href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.7">Release</a></nav>
47
47
  </header>
48
48
  <main>
49
49
  <section class="hero" style="border:0;padding-bottom:22px">
@@ -54,7 +54,7 @@ footer{padding:34px 0 48px;color:var(--muted);font-size:12px}
54
54
  <div class="install">curl -fsSL https://raw.githubusercontent.com/Lencen/dsh-agent-lines/main/install.sh -o install.sh &amp;&amp; bash install.sh</div>
55
55
  <div class="actions">
56
56
  <a class="btn primary" href="https://github.com/Lencen/dsh-agent-lines">GitHub repository</a>
57
- <a class="btn" href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.6">Download 0.3.6</a>
57
+ <a class="btn" href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.7">Download 0.3.7</a>
58
58
  </div>
59
59
  </div>
60
60
  <div class="shot">
@@ -92,8 +92,8 @@ research (调研), architecture (架构), uiux (UIUX), dev (开发), test (测
92
92
  After the team is ready, wait for my first task. Do not start by yourself.</pre>
93
93
  <p style="color:var(--muted);font-size:14px">Restart DSH Web after install or update. Technical details, protocol, and limits: <a href="https://github.com/Lencen/dsh-agent-lines">README / architecture</a>. Community plugin, not an official DeepSeek product.</p>
94
94
  </section>
95
- <footer>dsh-agent-lines 0.3.6 · Apache-2.0 · Community plugin for DeepSeek Harness. Not an official DeepSeek product.</footer>
95
+ <footer>dsh-agent-lines 0.3.7 · Apache-2.0 · Community plugin for DeepSeek Harness. Not an official DeepSeek product.</footer>
96
96
  </main>
97
97
  </div>
98
98
  </body>
99
- </html>
99
+ </html>
package/docs/index.html CHANGED
@@ -43,7 +43,7 @@ footer{padding:34px 0 48px;color:var(--muted);font-size:12px}
43
43
  <div class="wrap">
44
44
  <header>
45
45
  <a class="brand" href="./"><span class="mark"></span>dsh-agent-lines</a>
46
- <nav><a href="en/index.html">English</a><a href="https://github.com/Lencen/dsh-agent-lines">GitHub</a><a href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.6">Release</a></nav>
46
+ <nav><a href="en/index.html">English</a><a href="https://github.com/Lencen/dsh-agent-lines">GitHub</a><a href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.7">Release</a></nav>
47
47
  </header>
48
48
  <main>
49
49
  <section class="hero" style="border:0;padding-bottom:22px">
@@ -54,7 +54,7 @@ footer{padding:34px 0 48px;color:var(--muted);font-size:12px}
54
54
  <div class="install">curl -fsSL https://raw.githubusercontent.com/Lencen/dsh-agent-lines/main/install.sh -o install.sh &amp;&amp; bash install.sh</div>
55
55
  <div class="actions">
56
56
  <a class="btn primary" href="https://github.com/Lencen/dsh-agent-lines">GitHub 仓库</a>
57
- <a class="btn" href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.6">下载 0.3.6</a>
57
+ <a class="btn" href="https://github.com/Lencen/dsh-agent-lines/releases/tag/v0.3.7">下载 0.3.7</a>
58
58
  </div>
59
59
  </div>
60
60
  <div class="shot">
@@ -92,8 +92,8 @@ research(调研)、architecture(架构)、uiux(UIUX)、dev(开发
92
92
  团队建好后先待命,不要自动开工,等我发第一个任务。</pre>
93
93
  <p style="color:var(--muted);font-size:14px">安装或更新后需要重启 DSH Web。技术细节、协议和限制见 <a href="https://github.com/Lencen/dsh-agent-lines">README / 架构文档</a>。社区插件,不是 DeepSeek 官方产品。</p>
94
94
  </section>
95
- <footer>dsh-agent-lines 0.3.6 · Apache-2.0 · Community plugin for DeepSeek Harness. Not an official DeepSeek product.</footer>
95
+ <footer>dsh-agent-lines 0.3.7 · Apache-2.0 · Community plugin for DeepSeek Harness. Not an official DeepSeek product.</footer>
96
96
  </main>
97
97
  </div>
98
98
  </body>
99
- </html>
99
+ </html>
@@ -50,11 +50,11 @@
50
50
  ]
51
51
  },
52
52
  "dist-tags": {
53
- "latest": "0.3.6"
53
+ "latest": "0.3.7"
54
54
  },
55
55
  "versions": [
56
56
  {
57
- "version": "0.3.6",
57
+ "version": "0.3.7",
58
58
  "publishTimestamp": 1793771000,
59
59
  "source": {
60
60
  "type": "npm"
@@ -66,4 +66,4 @@
66
66
  ]
67
67
  }
68
68
  ]
69
- }
69
+ }
@@ -0,0 +1,16 @@
1
+ # Dashboard example
2
+
3
+ The plugin deliberately does not run an HTTP server. Read the same SQLite queue with:
4
+
5
+ ~~~bash
6
+ dsh-agent-lines --json list
7
+ ~~~
8
+
9
+ Fields: label/title/role/lifecycle/generation/pending/unread/lastActivityAt/lease.
10
+ The Surface feedback dashboard (refresh-dashboard.js) can consume this JSON and keep its own directory scan.
11
+
12
+ For a handoff snapshot before replacing a line:
13
+
14
+ ~~~text
15
+ line_handoff({ line: "writer", format: "json" })
16
+ ~~~
@@ -50,11 +50,11 @@
50
50
  ]
51
51
  },
52
52
  "dist-tags": {
53
- "latest": "0.3.6"
53
+ "latest": "0.3.7"
54
54
  },
55
55
  "versions": [
56
56
  {
57
- "version": "0.3.6",
57
+ "version": "0.3.7",
58
58
  "publishTimestamp": 1793771000,
59
59
  "source": {
60
60
  "type": "npm"
@@ -66,4 +66,4 @@
66
66
  ]
67
67
  }
68
68
  ]
69
- }
69
+ }
package/lib/delivery.js CHANGED
File without changes
package/lib/index.js CHANGED
@@ -297,7 +297,7 @@ export async function apply(ctx, rawConfig) {
297
297
 
298
298
  const lineTitle = (def, row) => String((row && row.title) || (def && def.title) || (def && def.role) || (def && def.label) || 'agent line').slice(0, 120)
299
299
 
300
- const rebindLine = async ({ label, sessionId, actor, reason, migrate = 'queued', force = false }) => {
300
+ const rebindLine = async ({ label, sessionId, actor, reason, migrate = 'queued', force = false, notify = true }) => {
301
301
  if (label === config.createFrom) throw new LineError('LINE_MANAGER_REBIND_UNSUPPORTED', 'The manager line is rebound with line_claim_manager, not line_rebind', { line: label })
302
302
  const row = store.getLineRow(config.agentId, label)
303
303
  if (row === undefined) throw new LineError('LINE_NOT_FOUND', `No such line: ${config.agentId}#${label}`)
@@ -332,6 +332,15 @@ export async function apply(ctx, rawConfig) {
332
332
  startLoop(def)
333
333
  const agent = ctx.agents.get(sessionId)
334
334
  if (agent !== undefined) bindAgent(agent)
335
+ if (notify !== false) {
336
+ try {
337
+ store.send({
338
+ agentId: config.agentId, fromLine: config.createFrom, to: label,
339
+ text: `[Agent Line] ${label} switched to a fresh Session. old=${row.session_id} new=${sessionId} migrated=${JSON.stringify(updated.counts)}. Read the handoff file before continuing.`,
340
+ noReply: true, maxReplyDepth: config.maxReplyDepth, maxMessageBytes: config.maxMessageBytes,
341
+ })
342
+ } catch (error) { ctx.logger?.warn?.('agent-lines: rebind notification failed: %s', String(error)) }
343
+ }
335
344
  return { line: label, oldSessionId: row.session_id, newSessionId: sessionId, generation: updated.generation, counts: updated.counts }
336
345
  } catch (error) {
337
346
  try { await stopLoopFor(label) } catch { /* best effort */ }
@@ -397,7 +406,7 @@ export async function apply(ctx, rawConfig) {
397
406
  const actualSessionId = created.sessionId
398
407
  const result = await rebindLine({
399
408
  label: existing.label, sessionId: actualSessionId, actor: (exec && exec.agent && exec.agent.session && exec.agent.session.id) || null,
400
- reason: String(args.reason || 'line_create replace'), migrate: args.migrate === 'none' ? 'none' : 'queued', force: args.force === true,
409
+ reason: String(args.reason || 'line_create replace'), migrate: args.migrate === 'none' ? 'none' : 'queued', force: args.force === true, notify: false,
401
410
  })
402
411
  const newDef = lineDefs.get(actualSessionId)
403
412
  if (newDef !== undefined) {
package/lib/prompt.js CHANGED
File without changes
package/lib/protocol.js CHANGED
File without changes
package/lib/store.js CHANGED
@@ -410,13 +410,19 @@ export class LineStore {
410
410
  /** All lines with unread counts and live lease state. */
411
411
  listLines(now = Date.now()) {
412
412
  const rows = this.#stmt(`SELECT l.*, (SELECT COUNT(*) FROM messages m
413
- WHERE m.to_agent = l.agent_id AND m.to_line = l.label AND m.state IN ('queued', 'claimed', 'delivered')) AS unread
413
+ WHERE m.to_agent = l.agent_id AND m.to_line = l.label AND m.state IN ('queued', 'claimed', 'delivered')) AS unread,
414
+ (SELECT COUNT(*) FROM messages m
415
+ WHERE m.to_agent = l.agent_id AND m.to_line = l.label AND m.state IN ('queued', 'claimed')) AS pending,
416
+ (SELECT MAX(m.created_at) FROM messages m
417
+ WHERE m.to_agent = l.agent_id AND m.to_line = l.label) AS last_activity_at
414
418
  FROM lines l ORDER BY l.agent_id, l.label`).all()
415
419
  return rows.map(row => {
416
420
  const lease = this.#stmt('SELECT * FROM leases WHERE line_id = ?').get(row.line_id)
417
421
  return {
418
422
  ...row,
419
423
  unread: Number(row.unread),
424
+ pending: Number(row.pending ?? 0),
425
+ lastActivityAt: row.last_activity_at === null ? null : Number(row.last_activity_at),
420
426
  lease: lease === undefined ? null : {
421
427
  instanceId: lease.instance_id,
422
428
  expiresAt: lease.expires_at,
@@ -433,9 +439,13 @@ export class LineStore {
433
439
  if (row === undefined) return undefined
434
440
  const lease = this.#stmt('SELECT * FROM leases WHERE line_id = ?').get(id)
435
441
  const unread = this.#stmt(`SELECT COUNT(*) AS n FROM messages WHERE to_agent = ? AND to_line = ? AND state IN ('queued', 'claimed', 'delivered')`).get(agentId, line)
442
+ const pending = this.#stmt(`SELECT COUNT(*) AS n FROM messages WHERE to_agent = ? AND to_line = ? AND state IN ('queued', 'claimed')`).get(agentId, line)
443
+ const activity = this.#stmt('SELECT MAX(created_at) AS n FROM messages WHERE to_agent = ? AND to_line = ?').get(agentId, line)
436
444
  return {
437
445
  ...row,
438
446
  unread: Number(unread.n),
447
+ pending: Number(pending.n),
448
+ lastActivityAt: activity.n === null ? null : Number(activity.n),
439
449
  lease: lease === undefined ? null : { instanceId: lease.instance_id, expiresAt: lease.expires_at, live: lease.expires_at > now },
440
450
  }
441
451
  }
@@ -532,6 +542,22 @@ export class LineStore {
532
542
  return this.#stmt('SELECT * FROM line_events WHERE line_id = ? AND action = ? ORDER BY created_at DESC LIMIT 1').get(id, action)
533
543
  }
534
544
 
545
+ /** Structured handoff snapshot: counts + recent messages + lifecycle events. */
546
+ handoff({ agentId, line, limit = 20, now = Date.now() }) {
547
+ const row = this.getLine(agentId, line, now)
548
+ if (row === undefined) throw new LineError('LINE_NOT_FOUND', `No such line: ${lineId(agentId, line)}`)
549
+ const recent = this.#stmt(`SELECT * FROM messages WHERE to_agent = ? AND to_line = ? ORDER BY created_at DESC LIMIT ?`).all(agentId, line, limit).reverse()
550
+ const events = this.lineEvents({ agentId, line, limit: 10 })
551
+ const lastEvent = events.length ? events[0] : null
552
+ return {
553
+ line: line, label: line, role: row.role, title: row.title ?? row.role ?? row.label,
554
+ sessionId: row.session_id, lifecycle: row.lifecycle ?? 'active', generation: row.generation ?? 1,
555
+ createdBy: row.created_by, createdAt: row.created_at, counts: this.messageCounts({ agentId, line }),
556
+ lastActivityAt: row.lastActivityAt, oldSessionId: lastEvent && lastEvent.action === 'rebind' ? lastEvent.old_session_id : null,
557
+ lastEvent, events, messages: recent,
558
+ }
559
+ }
560
+
535
561
  /** Recent lifecycle events for diagnostics. */
536
562
  lineEvents({ agentId, line, limit = 20 }) {
537
563
  const id = lineId(agentId, line)
package/lib/tools.js CHANGED
@@ -98,6 +98,9 @@ export function registerStatusTool(ctx, { config, store, lineDefs }) {
98
98
  title: line.title ?? line.role ?? line.label,
99
99
  lifecycle: line.lifecycle ?? 'active',
100
100
  generation: line.generation ?? 1,
101
+ oldSessionId: store.lastLineEvent({ agentId: line.agent_id, line: line.label, action: 'rebind' })?.old_session_id ?? null,
102
+ pending: line.pending ?? 0,
103
+ lastActivityAt: line.lastActivityAt ?? null,
101
104
  sessionId: line.session_id,
102
105
  createdBy: line.created_by,
103
106
  lease: line.lease,
@@ -383,6 +386,56 @@ export function registerToolsForAgent(agent, def, { config, store, lineDefs, cre
383
386
  },
384
387
  }))
385
388
 
389
+ disposers.push(agent.ctx.tools.register({
390
+ name: 'line_handoff',
391
+ description: 'Generate a structured handoff snapshot for a line: current metadata, backlog counts, recent messages, lifecycle events. Does not call a model; write the returned markdown to a file before retire/replace/rebind.',
392
+ parameters: {
393
+ type: 'object', additionalProperties: false,
394
+ properties: {
395
+ line: { type: 'string', description: 'Existing line label' },
396
+ format: { type: 'string', enum: ['md', 'json'], description: 'md (default) returns markdown; json returns the snapshot object' },
397
+ limit: { type: 'number', description: 'Recent messages to include, 1-100 (default 20)' },
398
+ },
399
+ required: ['line'],
400
+ },
401
+ output: OUTPUT,
402
+ execute: async (args, exec) => {
403
+ const caller = currentLine(exec, lineDefs)
404
+ if (caller.label !== config.createFrom) throw new LineError('LINE_CREATE_FORBIDDEN', `Only ${config.createFrom} may create handoffs`, { caller: caller.label })
405
+ const limit = limitValue(args.limit, 20, 100)
406
+ const data = store.handoff({ agentId: config.agentId, line: String(args.line), limit })
407
+ if (args.format === 'json') return data
408
+ const lines = [
409
+ '# 交接单 · ' + data.label,
410
+ '',
411
+ '## 1 我是谁',
412
+ '- 角色: ' + (data.role ?? data.label),
413
+ '- 当前 label: ' + data.label,
414
+ '- Session: ' + data.sessionId,
415
+ '- lifecycle: ' + data.lifecycle + ' (generation ' + data.generation + ')',
416
+ '',
417
+ '## 2 积压',
418
+ '- queued: ' + data.counts.queued,
419
+ '- claimed: ' + data.counts.claimed,
420
+ '- delivered: ' + data.counts.delivered,
421
+ '- acked: ' + data.counts.acked,
422
+ '- failed/expired: ' + (data.counts.failed + data.counts.expired),
423
+ '',
424
+ '## 3 最近消息',
425
+ ...(data.messages.length === 0 ? ['- 无'] : data.messages.map(m => `- ${new Date(m.created_at).toISOString()} [${m.state}] ${m.from_line} -> ${m.to_line}: ${String(m.body).replace(/\s+/g, ' ').slice(0, 180)}`)),
426
+ '',
427
+ '## 4 生命周期',
428
+ ...(data.events.length === 0 ? ['- 无'] : data.events.map(e => `- ${new Date(e.created_at).toISOString()} ${e.action} ${e.old_session_id ? e.old_session_id + ' -> ' : ''}${e.new_session_id ?? ''}`)),
429
+ '',
430
+ '## 5 交接提示',
431
+ '- 先读本文件,再继续工作。',
432
+ '- 不要复用旧 Session;它只保留历史。',
433
+ '- 如有 queued/claimed,新线会继续收到。',
434
+ ]
435
+ return { line: data.label, format: 'md', markdown: lines.join('\n'), counts: data.counts, sessionId: data.sessionId, generation: data.generation }
436
+ },
437
+ }))
438
+
386
439
  disposers.push(agent.ctx.tools.register({
387
440
  name: 'line_move_workspace',
388
441
  description: 'Move an existing line Session into a target workspace record so it appears under that workspace in the sidebar. DSH only allows attachment when the Session cwd exactly matches the workspace path; it cannot move a Session to a different directory (use a new line for that).',
package/lib/transport.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-agent-lines",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "DSH Agent 的持久、可寻址消息线(社区插件)。",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",