@a1hvdy/cc-openclaw 0.27.9 → 0.27.10

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.
@@ -346,9 +346,12 @@ export function renderTurn(turn, meta) {
346
346
  push(`<b>${escapeHtml(status)}</b>`);
347
347
  // v0.26.2 M2 — meter row (context % + quota % + reset). Same no-fake-data
348
348
  // gating: omitted unless real values are present. HTML-escaped for safety.
349
+ // v0.27.10 — wrap the meter row in <code> so the bars read as one cohesive
350
+ // monospace status widget (ctx ▓▓░ 6% · use …) instead of loose plain text
351
+ // sitting under the bold header — part of the "solid HTML" cleanup.
349
352
  const meters = renderMeters(meta);
350
353
  if (meters)
351
- push(escapeHtml(meters));
354
+ push(`<code>${escapeHtml(meters)}</code>`);
352
355
  // v0.26.4 styling — divider between the status/telemetry block and the
353
356
  // activity block (only when a status block was actually rendered). The
354
357
  // heavy-bar glyph is not HTML-significant, so it needs no escaping.
@@ -362,7 +365,10 @@ export function renderTurn(turn, meta) {
362
365
  : turn.state === 'done'
363
366
  ? '✓ Done'
364
367
  : '▶ Working';
365
- push(header);
368
+ // v0.27.10 — bold the turn-status header so it anchors the activity block as a
369
+ // styled heading rather than a plain line (cohesion pass). failReason is already
370
+ // escapeHtml'd above; ✓ Done / ▶ Working are literal-safe.
371
+ push(`<b>${header}</b>`);
366
372
  if (turn.toolCalls.length > 0) {
367
373
  // Build tool ENTRIES (tool line + its optional <pre><code> result block)
368
374
  // newest-first, keeping what fits under budget; the older overflow collapses
@@ -611,10 +611,17 @@ export class PersistentClaudeSession extends EventEmitter {
611
611
  this.stats.tokensOut += usage.output_tokens || 0;
612
612
  this.stats.cachedTokens += usage.cache_read_input_tokens || 0;
613
613
  // v0.6.0: track actual per-turn context occupancy for the contextPercent
614
- // calc. cache_read_input_tokens DO occupy the window; input_tokens are
615
- // the new uncached prefix. Together they approximate real window usage.
614
+ // calc. v0.27.10: include cache_creation_input_tokens. The full prompt
615
+ // sent each turn = input (new uncached) + cache_read (cached prefix
616
+ // re-read) + cache_creation (newly written to cache). Summing ALL THREE
617
+ // yields the true current context-window occupancy, stable across cache
618
+ // hit/miss. Omitting cache_creation made the meter swing wildly (cold
619
+ // cache → everything is creation, uncounted → ~6%; warm cache → big
620
+ // read → 63%+) — the exact 6%→63%→100% jitter A1 flagged 2026-05-22.
616
621
  this.stats.lastTurnContextTokens =
617
- (usage.input_tokens || 0) + (usage.cache_read_input_tokens || 0);
622
+ (usage.input_tokens || 0) +
623
+ (usage.cache_read_input_tokens || 0) +
624
+ (usage.cache_creation_input_tokens || 0);
618
625
  this._updateCost();
619
626
  }
620
627
  this.emit(SESSION_EVENT.RESULT, event);
@@ -223,6 +223,19 @@ export function markdownToHtml(input) {
223
223
  // glyph isn't HTML-significant, so it survives the escape below. Uses [ \t]
224
224
  // (not \s) so it never consumes the line break.
225
225
  text = text.replace(/^([ \t]*)[-*+][ \t]+/gm, (_m, indent) => `${indent}• `);
226
+ // v0.27.10 — strip dangling inline-markdown delimiters left by PARTIAL
227
+ // streaming text. Every CLOSED span (```fence```, `code`, **bold**, ~~strike~~)
228
+ // was already lifted out to a NUL placeholder above; whatever **, ~~ or ` is
229
+ // still here is an UNTERMINATED marker at the live-stream frontier (e.g. the
230
+ // card edited mid-token while the model is still typing "…and the **bold"). Left
231
+ // in place it renders as a raw symbol next to formatted text — the "normal text
232
+ // mixed between HTML" A1 flagged 2026-05-22. Remove the markers, keep the words.
233
+ // Finalized (balanced) text has none left, so this is a no-op there. `*`/`_` are
234
+ // deliberately NOT stripped (too easily literal math / snake_case → false hits).
235
+ text = text
236
+ .replace(/\*\*/g, '')
237
+ .replace(/~~/g, '')
238
+ .replace(/`/g, '');
226
239
  text = escapeHtml(text);
227
240
  text = text.replace(/\x00CODEBLOCK(\d+)\x00/g, (_m, idx) => codeBlocks[Number(idx)]);
228
241
  text = text.replace(/\x00TABLE(\d+)\x00/g, (_m, idx) => tables[Number(idx)]);
@@ -219,7 +219,7 @@ export function resolveProvider(model) {
219
219
  }
220
220
  /** Get context window size for a model. Returns 200k default for unknown models. */
221
221
  export function getContextWindow(model) {
222
- const clean = model.replace(/^(anthropic|openai|openai-codex|google|gemini|cursor)\//g, '');
222
+ const clean = model.replace(/^(anthropic|openai|openai-codex|google|gemini|cursor|cc-openclaw)\//g, '');
223
223
  const known = lookupModel(clean);
224
224
  return known?.contextWindow ?? 200_000;
225
225
  }
@@ -227,7 +227,7 @@ export function getContextWindow(model) {
227
227
  export function getModelPricing(model, defaultModel = 'claude-sonnet-4-6') {
228
228
  if (!model)
229
229
  return lookupModel(defaultModel)?.pricing ?? { input: 0, output: 0 };
230
- const clean = model.replace(/^(anthropic|openai|openai-codex|google|gemini|cursor)\//g, '');
230
+ const clean = model.replace(/^(anthropic|openai|openai-codex|google|gemini|cursor|cc-openclaw)\//g, '');
231
231
  // Check overrides first
232
232
  const override = _pricingOverrides.get(clean);
233
233
  if (override)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a1hvdy/cc-openclaw",
3
- "version": "0.27.9",
3
+ "version": "0.27.10",
4
4
  "description": "A1xAI's Anthropic CLI bridge plugin for OpenClaw",
5
5
  "author": "@a1cy",
6
6
  "license": "MIT",