@raquezha/noheadroom 0.3.3 → 0.3.5

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/dist/bridge.js CHANGED
@@ -57,9 +57,11 @@ export function applyCompressionResult(originalMessages, mappings, compressedMes
57
57
  const nextText = extractOpenAIText(compressed);
58
58
  if (nextText === mapping.originalText)
59
59
  continue;
60
- // No retrieval executor is registered. Hiding a hash does not recover evidence.
61
- if (CCR_MARKER.test(nextText))
60
+ // No retrieval executor is registered. Reject only a marker created by this response:
61
+ // prior session history can already contain one and must not disable later safe compaction.
62
+ if (CCR_MARKER.test(nextText) && !CCR_MARKER.test(mapping.originalText)) {
62
63
  return { ok: false, reason: "unrecoverable-ccr-marker" };
64
+ }
63
65
  if (!nextText.trim())
64
66
  return { ok: false, reason: "empty-compressed-content" };
65
67
  if (estimateTokens(nextText) >= estimateTokens(mapping.originalText))
package/dist/client.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { CompressResult, OpenAIMessage } from "./types.js";
2
+ export declare class HeadroomResponseError extends Error {
3
+ }
2
4
  interface HeadroomClientOptions {
3
5
  baseUrl: string;
4
6
  timeoutMs: number;
package/dist/client.js CHANGED
@@ -1,3 +1,5 @@
1
+ export class HeadroomResponseError extends Error {
2
+ }
1
3
  export class HeadroomHttpClient {
2
4
  baseUrl;
3
5
  timeoutMs;
@@ -87,8 +89,8 @@ function validateCompressionResponse(value) {
87
89
  if (!isRecord(value) || !Array.isArray(value.messages) ||
88
90
  !metrics.every((key) => typeof value[key] === "number" && Number.isFinite(value[key]) && value[key] >= 0) ||
89
91
  (value.transforms_applied !== undefined && !stringArray(value.transforms_applied)) ||
90
- (value.ccr_hashes !== undefined && (!stringArray(value.ccr_hashes) || value.ccr_hashes.length > 0))) {
91
- throw new Error("Invalid or retrieval-dependent Headroom compression response");
92
+ (value.ccr_hashes != null && !stringArray(value.ccr_hashes))) {
93
+ throw new HeadroomResponseError("Invalid Headroom compression response");
92
94
  }
93
95
  return value;
94
96
  }
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { Box, Text } from "@earendil-works/pi-tui";
3
3
  import { applyCompressionResult, buildCompressionPayload, convertMessage, extractOpenAIText, } from "./bridge.js";
4
- import { HeadroomHttpClient } from "./client.js";
4
+ import { HeadroomHttpClient, HeadroomResponseError } from "./client.js";
5
5
  import { isRemoteBlocked, loadHeadroomConfig, saveHeadroomSettings } from "./config.js";
6
6
  import { startPersistentHeadroomProxy } from "./proxy-manager.js";
7
7
  const STATUS_KEY = "headroom";
@@ -534,7 +534,8 @@ function announceGuardSkip(ctx, reason, result, mode = "normal") {
534
534
  }
535
535
  function recordCompressionError(runtime, ctx, error) {
536
536
  runtime.state.stats.lastError = getErrorMessage(error);
537
- if (isAbortOrTimeoutError(error)) {
537
+ if (isAbortOrTimeoutError(error) || error instanceof HeadroomResponseError) {
538
+ // The proxy answered; invalid data is not a connectivity failure.
538
539
  emitNotraceTelemetry(runtime);
539
540
  runtime.refreshStatus(ctx);
540
541
  return;
@@ -87,8 +87,11 @@ export function applyCompressionResult(
87
87
 
88
88
  const nextText = extractOpenAIText(compressed);
89
89
  if (nextText === mapping.originalText) continue;
90
- // No retrieval executor is registered. Hiding a hash does not recover evidence.
91
- if (CCR_MARKER.test(nextText)) return { ok: false, reason: "unrecoverable-ccr-marker" };
90
+ // No retrieval executor is registered. Reject only a marker created by this response:
91
+ // prior session history can already contain one and must not disable later safe compaction.
92
+ if (CCR_MARKER.test(nextText) && !CCR_MARKER.test(mapping.originalText)) {
93
+ return { ok: false, reason: "unrecoverable-ccr-marker" };
94
+ }
92
95
  if (!nextText.trim()) return { ok: false, reason: "empty-compressed-content" };
93
96
  if (estimateTokens(nextText) >= estimateTokens(mapping.originalText)) continue;
94
97
 
@@ -10,6 +10,8 @@ interface ProxyCompressResponse {
10
10
  ccr_hashes?: string[];
11
11
  }
12
12
 
13
+ export class HeadroomResponseError extends Error {}
14
+
13
15
  interface HeadroomClientOptions {
14
16
  baseUrl: string;
15
17
  timeoutMs: number;
@@ -108,8 +110,8 @@ function validateCompressionResponse(value: unknown): ProxyCompressResponse {
108
110
  if (!isRecord(value) || !Array.isArray(value.messages) ||
109
111
  !metrics.every((key) => typeof value[key] === "number" && Number.isFinite(value[key]) && value[key] >= 0) ||
110
112
  (value.transforms_applied !== undefined && !stringArray(value.transforms_applied)) ||
111
- (value.ccr_hashes !== undefined && (!stringArray(value.ccr_hashes) || (value.ccr_hashes as string[]).length > 0))) {
112
- throw new Error("Invalid or retrieval-dependent Headroom compression response");
113
+ (value.ccr_hashes != null && !stringArray(value.ccr_hashes))) {
114
+ throw new HeadroomResponseError("Invalid Headroom compression response");
113
115
  }
114
116
  return value as unknown as ProxyCompressResponse;
115
117
  }
@@ -7,7 +7,7 @@ import {
7
7
  convertMessage,
8
8
  extractOpenAIText,
9
9
  } from "./bridge.js";
10
- import { HeadroomHttpClient } from "./client.js";
10
+ import { HeadroomHttpClient, HeadroomResponseError } from "./client.js";
11
11
  import { isRemoteBlocked, loadHeadroomConfig, saveHeadroomSettings } from "./config.js";
12
12
  import { startPersistentHeadroomProxy } from "./proxy-manager.js";
13
13
  import type { AgentMessage, CompressResult, CompressionPayload, HeadroomConfig, HeadroomMode, HeadroomStats } from "./types.js";
@@ -610,7 +610,8 @@ function announceGuardSkip(ctx: ExtensionContext, reason: string, result: Compre
610
610
 
611
611
  function recordCompressionError(runtime: HeadroomRuntime, ctx: ExtensionContext, error: unknown): void {
612
612
  runtime.state.stats.lastError = getErrorMessage(error);
613
- if (isAbortOrTimeoutError(error)) {
613
+ if (isAbortOrTimeoutError(error) || error instanceof HeadroomResponseError) {
614
+ // The proxy answered; invalid data is not a connectivity failure.
614
615
  emitNotraceTelemetry(runtime);
615
616
  runtime.refreshStatus(ctx);
616
617
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raquezha/noheadroom",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Personal Headroom compression bridge for Pi with Docker-first defaults and Pi tool-name adaptation",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",