@falling-ts/dsh-force-compact 0.2.5 → 0.2.6

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/index.js CHANGED
@@ -56,6 +56,7 @@ void thinkingDisabled
56
56
  import { registerCommand } from './src/hooks/command.js'
57
57
  import { handleAgentStatus } from './src/hooks/idle.js'
58
58
  import { registerLlmStreamHook } from './src/hooks/wire-rewrite.js'
59
+ import { publishWorkingOnStart } from './src/core/ui-signal.js'
59
60
  import { guardFn, installCrashNet } from './src/core/crashnet.js'
60
61
 
61
62
  /** @type {string} the function plugin's display name. */
@@ -373,6 +374,19 @@ const __applyInner = (ctx) => {
373
374
  maybeRegisterSettingsNamespace()
374
375
  maybeRegisterCommand()
375
376
  maybeInstallWireRewrite()
377
+ // CONVERSATION-START Live-UI FORCED OVERRIDE (self-healing): this seam is
378
+ // the FIRST model request of a conversation step, so force-clear any stale
379
+ // pinned bracket-form text ([强制压缩中>>>] / [压缩完成!] residue left by an
380
+ // interrupted or failed compaction) with a fresh random working pair
381
+ // (isImportant=true). Without this the non-important guard inside
382
+ // publishUiStatus would refuse to overwrite a `[`-prefixed text and the
383
+ // badge could stay frozen on a stale banner for the whole session. Fire-
384
+ // and-forget, like the llm/stream watermark: publishWorkingOnStart swallows
385
+ // its own rejections internally and must never block the request chain.
386
+ // Mid-request watermarking stays NON-important (publishRandomWorking at the
387
+ // llm/stream hook) so a live compressing/done banner during an ACTUAL
388
+ // compaction still survives; only the START of a conversation clears it.
389
+ void publishWorkingOnStart(ctx)
376
390
  return await __agentRequestListenerBody(ctx, payload, next)
377
391
  } catch (error) {
378
392
  const message = error instanceof Error ? error.message : String(error)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@falling-ts/dsh-force-compact",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "DSH Cordis plugin: hooks the core model-request seam (agent/pre-step + agent/request) to force-compact a session's context and disable thinking per the \"强制压缩配置\" settings namespace (disableThinking, autoThresholdTokens, retainLatestTokens, turnEndForceCompactionEnabled). When the threshold fires (or /force-compact queues while busy), the latest `retainLatestTokens` of the conversation's surface tokens are KEPT VERBATIM and everything before that cutoff is COMPACTED INTO A SINGLE SUMMARY NODE in one LLM call (original span entries become shadowed/skipped). Also compacts at each turn/end and at each session/flush durability checkpoint. Host half is a pure listener; a web client half registers a settings.section (强制压缩 / Force Compact) that reads and writes the same settings namespace.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -227,6 +227,32 @@ export async function publishRandomWorking(ctx) {
227
227
  await publishUiStatus(ctx, randomWorkingPair())
228
228
  }
229
229
 
230
+ /**
231
+ * The conversation-START forced override: publish a fresh random working pair
232
+ * with `isImportant=true`, so it UNCONDITIONALLY overwrites whatever is
233
+ * currently displayed — including a stale pinned bracket-form text such as
234
+ * `[强制压缩中>>>]` left behind by an interrupted/failed compaction (the
235
+ * non-important guard inside {@link publishUiStatus} refuses to overwrite a
236
+ * `[`-prefixed text, so such residue would otherwise stick on the badge for
237
+ * the whole session, forever showing a frozen compressing/done banner instead
238
+ * of a live working label).
239
+ *
240
+ * Call ONCE at the START of a conversation step (the `agent/request` seam —
241
+ * see index.js): the first model request of a new turn force-clears any
242
+ * bracket residue so the badge immediately returns to a normal working look.
243
+ * Only the START uses the forced form; the mid-stream watermark keeps
244
+ * publishing NON-importantly via {@link publishRandomWorking} (called from the
245
+ * `llm/stream` hook) so a live `[强制压缩中>>>]` during an ACTUAL compaction
246
+ * still survives (the guard stays effective while something is really
247
+ * pressing). Clean, self-healing: a stale `[` never outlives the next
248
+ * conversation start.
249
+ * @param {import('@deepseek-ai/cordis').Context} ctx
250
+ * @returns {Promise<void>}
251
+ */
252
+ export async function publishWorkingOnStart(ctx) {
253
+ await publishUiStatus(ctx, randomWorkingPair(), true)
254
+ }
255
+
230
256
  /**
231
257
  * Publish the pinned RED "[强制压缩中>>>]" status. Call BEFORE a `compactNow` /
232
258
  * `compactRegion` invocation. Passes `isImportant=true` so the pinned