dsh-retrace 0.4.6 → 0.4.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.
@@ -121,9 +121,13 @@ return {
121
121
  content: [],
122
122
  source: { kind: 'model', provider: model.provider, model: model.model },
123
123
  }
124
+ // R2 路径一(2026-08-30 事故闭环):有打开的 step(回合中编辑)时,marker 携带
125
+ // 该 step 的 turn/step —— token-meter 配对通过,不产生 T1 违规、不刷屏。
126
+ // 无打开 step(轮次间编辑,常态)才回退 turn:null(配合 markerT1Broken 标注)。
127
+ const openStep = findOpenStep(session)
124
128
  const data = {
125
- turn: null,
126
- step: null,
129
+ turn: openStep ? openStep.turn : null,
130
+ step: openStep ? openStep.step : null,
127
131
  message: marker,
128
132
  editor: {
129
133
  targetSeq,
@@ -142,6 +146,24 @@ return {
142
146
  return session.append('assistant/message', data, { surfaceOp, sourceEventSeqs })
143
147
  }
144
148
 
149
+ /**
150
+ * 找当前打开的 step(最近一次未闭合的 step/start 的 turn/step)。
151
+ * 扫描 session.events:step/start 开、step/end 关;末尾仍开即返回。
152
+ * 无打开 step 返回 null(轮次间编辑)。
153
+ */
154
+ function findOpenStep(session) {
155
+ const events = Array.isArray(session?.events) ? session.events : []
156
+ let open = null
157
+ for (const event of events) {
158
+ if (event?.type === 'step/start') {
159
+ open = { turn: event.data?.turn, step: event.data?.step }
160
+ } else if (event?.type === 'step/end') {
161
+ open = null
162
+ }
163
+ }
164
+ return open
165
+ }
166
+
145
167
  function createEditorApi(ctx, sessions, agents, log = () => {}, hooks = {}) {
146
168
  /** One in-flight op per session; later ops wait for the earlier one. */
147
169
  const locks = new Map()
package/lib/host-core.js CHANGED
@@ -112,9 +112,13 @@ export async function appendEditorMarker(session, span, op, targetSeq, originalT
112
112
  content: [],
113
113
  source: { kind: 'model', provider: model.provider, model: model.model },
114
114
  }
115
+ // R2 路径一(2026-08-30 事故闭环):有打开的 step(回合中编辑)时,marker 携带
116
+ // 该 step 的 turn/step —— token-meter 配对通过,不产生 T1 违规、不刷屏。
117
+ // 无打开 step(轮次间编辑,常态)才回退 turn:null(配合 markerT1Broken 标注)。
118
+ const openStep = findOpenStep(session)
115
119
  const data = {
116
- turn: null,
117
- step: null,
120
+ turn: openStep ? openStep.turn : null,
121
+ step: openStep ? openStep.step : null,
118
122
  message: marker,
119
123
  editor: {
120
124
  targetSeq,
@@ -133,6 +137,24 @@ export async function appendEditorMarker(session, span, op, targetSeq, originalT
133
137
  return session.append('assistant/message', data, { surfaceOp, sourceEventSeqs })
134
138
  }
135
139
 
140
+ /**
141
+ * 找当前打开的 step(最近一次未闭合的 step/start 的 turn/step)。
142
+ * 扫描 session.events:step/start 开、step/end 关;末尾仍开即返回。
143
+ * 无打开 step 返回 null(轮次间编辑)。
144
+ */
145
+ export function findOpenStep(session) {
146
+ const events = Array.isArray(session?.events) ? session.events : []
147
+ let open = null
148
+ for (const event of events) {
149
+ if (event?.type === 'step/start') {
150
+ open = { turn: event.data?.turn, step: event.data?.step }
151
+ } else if (event?.type === 'step/end') {
152
+ open = null
153
+ }
154
+ }
155
+ return open
156
+ }
157
+
136
158
  export function createEditorApi(ctx, sessions, agents, log = () => {}, hooks = {}) {
137
159
  /** One in-flight op per session; later ops wait for the earlier one. */
138
160
  const locks = new Map()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-retrace",
3
3
  "description": "Retrace · 回溯 — Recall, edit-and-resend, regenerate, and conversation/artifact versioning (timeline, rollback, fork map) for DeepSeek Harness — Web and Desktop",
4
- "version": "0.4.6",
4
+ "version": "0.4.7",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/types/index.d.ts",