opencode-codeops 1.10.1 → 1.10.2

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.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to CodeOps are recorded here.
4
4
 
5
+ ## 1.10.2 — 2026-10-04
6
+
7
+ ### Fixes
8
+
9
+ - effort: remember dispatch markers per session
10
+
5
11
  ## 1.10.1 — 2026-10-04
6
12
 
7
13
  ### Features
@@ -43,6 +43,10 @@ A dispatch marker is one standalone line in a dispatch message:
43
43
  For quality-agent packets the marker follows the dispatch header; for packet kinds without a
44
44
  header it is the first line. `exec-plan` owns the composition rule.
45
45
 
46
+ A captured marker is remembered for the whole session: every request in that session uses it
47
+ until a newer marker replaces it or the session ends. This is what keeps the marker effective
48
+ when the host passes a later user message to the request hook.
49
+
46
50
  ## Precedence
47
51
 
48
52
  The most specific source wins:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-codeops",
3
- "version": "1.10.1",
3
+ "version": "1.10.2",
4
4
  "description": "Specification-first engineering for complex systems — CodeOps plugin for OpenCode",
5
5
  "type": "module",
6
6
  "engines": {
package/plugin/index.ts CHANGED
@@ -196,9 +196,9 @@ function traceEffort(
196
196
  // ---------------------------------------------------------------------------
197
197
  export const CodeOpsPlugin: Plugin = async ({ client, directory }) => {
198
198
  // Reasoning-effort state lives for the lifetime of this plugin instance:
199
- // one entry per user message that carried a dispatch marker, plus a
200
- // deduplication set for unsupported-level warnings.
201
- const effortMarkers = new Map<string, { sessionID: string; level: EffortLevel }>()
199
+ // the latest dispatch-marker level per session, plus a deduplication set
200
+ // for unsupported-level warnings.
201
+ const effortMarkers = new Map<string, EffortLevel>()
202
202
  const warnedEffortLevels = new Set<string>()
203
203
  const effortTraceEnabled = isEffortTraceEnabled(process.env.CODEOPS_EFFORT_TRACE)
204
204
 
@@ -221,9 +221,7 @@ export const CodeOpsPlugin: Plugin = async ({ client, directory }) => {
221
221
  const info = (event.properties as { info: { id: string } }).info
222
222
  removeSessionTmpDir(info.id)
223
223
  try {
224
- for (const [messageID, entry] of effortMarkers) {
225
- if (entry.sessionID === info.id) effortMarkers.delete(messageID)
226
- }
224
+ effortMarkers.delete(info.id)
227
225
  } catch {
228
226
  await warnContentFree(client, "Could not clear captured reasoning-effort markers.")
229
227
  }
@@ -288,8 +286,9 @@ export const CodeOpsPlugin: Plugin = async ({ client, directory }) => {
288
286
 
289
287
  // -----------------------------------------------------------------------
290
288
  // Hook 6: capture a dispatch marker from an incoming user message. The
291
- // marker travels in the dispatch packet text; storing it by message id
292
- // lets the later chat.params hook apply it to the same request.
289
+ // marker travels in the dispatch packet text; it is remembered for the
290
+ // whole session, because the later chat.params hook receives the latest
291
+ // user message, which can differ from the message that carried it.
293
292
  // -----------------------------------------------------------------------
294
293
  "chat.message": async (input, output) => {
295
294
  try {
@@ -298,7 +297,7 @@ export const CodeOpsPlugin: Plugin = async ({ client, directory }) => {
298
297
  )
299
298
  const level = findEffortMarker(texts)
300
299
  if (level !== undefined) {
301
- effortMarkers.set(output.message.id, { sessionID: input.sessionID, level })
300
+ effortMarkers.set(input.sessionID, level)
302
301
  traceEffort(effortTraceEnabled, input.sessionID, {
303
302
  event: "capture",
304
303
  messageID: output.message.id,
@@ -317,8 +316,7 @@ export const CodeOpsPlugin: Plugin = async ({ client, directory }) => {
317
316
  // -----------------------------------------------------------------------
318
317
  "chat.params": async (input, output) => {
319
318
  try {
320
- const stored = effortMarkers.get(input.message.id)
321
- const marker = stored && stored.sessionID === input.sessionID ? stored.level : undefined
319
+ const marker = effortMarkers.get(input.sessionID)
322
320
  const session = readSessionEffort(input.sessionID)
323
321
  const routing = readRoutingReasoning(readRoutingConfig(directory), input.agent)
324
322
  const level = resolveEffort({ marker, session, routing })