dsh-plugin-subagent-bridge 0.13.0 → 0.13.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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/index.js +24 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -79,6 +79,8 @@ dsh_task({ sessionId: "session-…", prompt: "停一下,改成只跑单测", m
79
79
 
80
80
  `dsh_task` 对正在运行的会话默认会拒绝,错误信息里会提示改用 `steer`。
81
81
 
82
+ 第三个细节是返回值:插话的回复和原任务在**同一个回合**里,所以不能简单取"这一轮最后一条 assistant 文本"——那可能是原任务后面的步骤。桥会在插话后定位到**自己那条 user/message**,只取它之后的 assistant 文本作为回答。
83
+
82
84
  ## 创建项目(workspace)
83
85
 
84
86
  DSH 的侧边栏分组是"项目(workspace)",和会话的工作目录是两回事:新建会话默认落在「未分组」,除非它所在的目录已经是一个项目。
package/index.js CHANGED
@@ -278,6 +278,26 @@ const TOOLS = [
278
278
  },
279
279
  ]
280
280
 
281
+ /**
282
+ * Sequence number of the first message the caller itself delivered after `sinceSeq`.
283
+ * With steer the reply shares the running turn, so "the last assistant text of the turn"
284
+ * can be a step of the original task; anchoring on our own message keeps it exact.
285
+ * @param ctx - Host context.
286
+ * @param sessionId - session to read.
287
+ * @param sinceSeq - sequence captured before the prompt was delivered.
288
+ * @returns the sequence, or the original value when nothing matches.
289
+ */
290
+ function firstDeliveredMessageSeq(ctx, sessionId, sinceSeq) {
291
+ const session = ctx.get('sessions')?.get?.(sessionId)
292
+ if (session === undefined || session === null) return sinceSeq
293
+ for (const event of session.snapshotEvents()) {
294
+ if (Number(event.seq) <= sinceSeq) continue
295
+ if (event.type !== 'user/message') continue
296
+ return Number(event.seq)
297
+ }
298
+ return sinceSeq
299
+ }
300
+
281
301
  /**
282
302
  * Start the bridge.
283
303
  * @param ctx - Host context.
@@ -908,7 +928,10 @@ export function createApi(ctx, state, settings) {
908
928
  }
909
929
 
910
930
  const end = await finished
911
- const collected = finalAnswer(ctx, targetId, before, settings)
931
+ /* A steered reply lives inside the turn that was already running, so anchor the
932
+ * answer on the message we delivered instead of the turn's last assistant text. */
933
+ const answerFrom = deliveryMode === 'steer' ? firstDeliveredMessageSeq(ctx, targetId, before) : before
934
+ const collected = finalAnswer(ctx, targetId, answerFrom, settings)
912
935
  const turnReason = end?.reason?.kind ?? null
913
936
  const durationMs = Date.now() - started
914
937
  const status = end === undefined ? 'timeout' : turnReason === 'completed' ? 'completed' : `turn-${String(turnReason)}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-subagent-bridge",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "type": "module",
5
5
  "description": "Subagent bridge: lets Codex delegate a task to DeepSeek Harness the way it would spawn a subagent (one call, waits for the answer), plus a codex_dispatch tool for the reverse direction.",
6
6
  "keywords": [