openclaw - ✅(Solved) Fix [Bug]: ACP background-task summary corrupts token-streamed text (CJK breaks into single chars, paths split with spaces) [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#78312Fetched 2026-05-07 03:38:24
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
2
Author
Timeline (top)
cross-referenced ×2labeled ×2closed ×1commented ×1

appendBackgroundTaskProgressSummary in src/acp/control-plane/manager.core.ts trims every streamed chunk and forces a join space, so any token-streamed text whose chunk boundaries fall inside a word loses those boundaries — 디렉토리 is rendered as 디 렉 토 리, and an English path like /home/bykim0119/.openclaw/workspace is rendered as / home / by kim 0119 / . open claw / workspace. The bug is most visible for CJK and for paths/URLs/identifiers, but it applies to any chunked stream where a chunk boundary is mid-word.

Root Cause

// English prose (incidentally fine because BPE leading-space tokens // happen to align with the forced-space behavior) run(["hello", " world"]); // "hello world" ✓ run(["hello ", "world"]); // "hello world" ✓

Fix Action

Fix / Workaround

  1. Configure ACP with acp.backend: "acpx", defaultAgent: "codex", dispatch.enabled: true.
  2. Have the orchestrator agent issue sessions_spawn(runtime: "acp", agentId: "codex", task: "<a Korean prompt that asks Codex to print an absolute path or any sentence>").
  3. Wait for the background task to complete; observe the auto-announced terminal summary in the parent channel.
  4. The Korean text in the announce is broken across characters with extra spaces inserted at every chunk boundary.

PR fix notes

PR #78319: fix(acp): preserve chunk whitespace in background-task progress summary [AI-Assisted]

Description (problem / solution / changelog)

Summary

  • Problem: appendBackgroundTaskProgressSummary in src/acp/control-plane/manager.core.ts trims every streamed chunk via normalizeOptionalString and joins with a forced single space, so token-streamed output whose chunk boundaries fall mid-word (CJK, paths, URLs, identifiers) loses inter-chunk word boundaries. Plain English prose escapes because BPE-style tokenizers prefix word tokens with a leading space, which incidentally aligns with the forced-space behavior.
  • Why it matters: parent-channel terminal summaries become unreadable for any non-English ACP workload, and for English content that mixes paths or identifiers. Users on mobile Discord lose the primary signal of background-task output and have to drop into the child session to read the real result.
  • What changed: drop the normalizeText/trim call on the chunk and the forced join space; concatenate the chunk verbatim after collapsing only its internal whitespace runs (newlines, tabs, multi-space) to a single space. Existing length cap and truncation marker are preserved. The helper is exported for direct unit testing. New focused unit-test file covers CJK one-char-per-chunk, path mid-segment, CamelCase mid-word, leading-/trailing-space, whitespace-run collapse, length cap, empty-chunk no-op, and successive empty-yielding chunks.
  • What did NOT change (scope boundary): no change to the cap value, the truncation marker, the taskProgressSummary / terminalSummary shape, or any downstream consumer. resolveBackgroundTaskTerminalResult and the success-path terminal-summary handling addressed by #74070 / PR #74103 are untouched — see "Scope vs #74070 / #74103" below.

Fixes #78312.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #78312
  • Related #74070, #74103
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: when Codex via ACP streams Korean output that includes a workspace path, the auto-announced terminal summary in the parent Discord channel renders inter-chunk word boundaries with spurious spaces (현재 작업 디 렉 토 리 는 / home / by kim 0119 / . open claw / workspace 입니다), losing both the CJK word grouping and the path separators. After the fix, the same announce renders the original text verbatim (현재 작업 디렉토리는 /home/bykim0119/.openclaw/workspace 입니다).

  • Real environment tested: production OpenClaw 2026.4.21 install (/usr/lib/node_modules/openclaw) on Ubuntu 24.04, Discord channel bound to a Hermes orchestrator agent, ACP backend acpx, child agent codex (Codex CLI 0.121.0, gpt-5.3-codex via ChatGPT Plus auth, ACP runtime spawned by sessions_spawn). The same appendBackgroundTaskProgressSummary source on main at 2026.5.5 has the identical buggy code path, confirmed by git show upstream/main:src/acp/control-plane/manager.core.ts | sed -n '99,109p'.

  • Exact steps or command run after this patch:

    1. Applied this patch's src/acp/control-plane/manager.core.ts change to the installed bundled file /usr/lib/node_modules/openclaw/dist/manager-BPXdclo2.js (the chunk-whitespace portion only — the cap and terminalSummary fields were left at their current upstream values).
    2. sudo systemctl restart openclaw.
    3. From the orchestrator agent in Discord: trigger a sessions_spawn(runtime: "acp", agentId: "codex", task: "<Korean prompt asking Codex to print the absolute path of its current working directory>").
    4. Waited for the background-task done announce to land in the parent channel; captured the rendered text.
    5. Locally, ran the new unit-test file: pnpm test src/acp/control-plane/manager.background-task-progress.test.ts.
  • Evidence after fix:

    Live Discord rendering of the announce after the patch (run 7495ffdbfec2c09c in OpenClaw's task-run log):

    현재 작업 디렉토리는 /home/bykim0119/.openclaw/workspace 입니다

    Same announce before the patch (same prompt, same agent, same model):

    현재 작업 디 렉 토 리 는 / home / by kim 0119 / . open claw / workspace 입니다

    Local unit-test output (10 deterministic cases including the live-mirroring CJK and path scenarios):

    RUN  v4.1.5 /home/bykim0119/autonormal/openclaw
    
     ✓ |unit-fast| src/acp/control-plane/manager.background-task-progress.test.ts (10 tests) 8ms
    
     Test Files  1 passed (1)
          Tests  10 passed (10)
       Duration  2.32s

    Existing manager test suite, run for regression coverage on the same change:

     ✓ |unit-fast| src/acp/control-plane/manager.test.ts (56 tests) 141ms
    
     Test Files  1 passed (1)
          Tests  56 passed (56)
       Duration  1.52s
  • Observed result after fix: the live announce in Discord renders the Korean and the path verbatim, matching what Codex actually emitted; chunked unit-test inputs (CJK syllables, path segments, mid-word identifier, leading-/trailing-space chunks, whitespace-run chunks, empty chunks, oversized inputs) all produce the expected concatenation; existing AcpSessionManager test suite still passes unchanged.

  • What was not tested: I did not exercise the non-Codex ACP runtimes (e.g. claude-code) end-to-end — the helper is generic and the unit tests cover the chunk surface, but live verification was only done against Codex via acpx. I did not run the full pnpm test / pnpm test:extensions suites locally; I ran pnpm check:changed --base upstream/main --head HEAD instead, which is the smart-gate equivalent for the changed paths and passed (typecheck core + core test, oxlint core, import-cycle, runtime-sidecar-loaders, webhook/auth guards, oxfmt).

  • Before evidence: same Korean prompt against the unpatched 2026.4.21 install:

    현재 작업 디 렉 토 리 는 / home / by kim 0119 / . open claw / workspace 입니다

    Programmatic before-state from the buggy helper (deterministic, no ACP runtime needed):

    run(["디", "렉", "토", "리"])               // "디 렉 토 리"
    run(["/home/", "user/", "file.", "txt"]) // "/home/ user/ file. txt"
    run(["unbeliev", "able"])                // "unbeliev able"

Root Cause (if applicable)

  • Root cause: normalizeText is normalizeOptionalString from src/shared/string-coerce.ts, which unconditionally .trim()s its input. That is the right contract for whole strings but wrong for streaming chunks: trimming strips the leading/trailing whitespace that carries the inter-chunk word-boundary signal. The downstream ${current} ${normalizedChunk} template then re-inserts a single space at every join, which produces visible gaps inside what was originally a single word for any tokenizer that splits chunks mid-word (CJK syllables, path segments, CamelCase identifiers).
  • Missing detection / guardrail: no unit test directly exercised appendBackgroundTaskProgressSummary with chunked inputs; the only coverage was via end-to-end AcpSessionManager tests that use English-only single-chunk inputs, which incidentally hide this regression class because BPE leading-space tokens align with the forced-space behavior.
  • Contributing context (if known): the helper was written against the assumption that the runtime emits whole-line progress strings; the assumption holds for some runtimes, but Codex's ACP runtime emits token-by-token progress, which exposes the chunk-boundary contract.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: new src/acp/control-plane/manager.background-task-progress.test.ts.
  • Scenario the test should lock in: appending a sequence of mid-word chunks (CJK syllables, path segments, mid-word identifiers) must concatenate verbatim, while leading-/trailing-space chunks, whitespace-run chunks, empty/non-string chunks, and oversized inputs still behave correctly.
  • Why this is the smallest reliable guardrail: the helper is pure, deterministic, and called per-chunk on the streaming path. A unit test directly on the helper deterministically catches any future regression of either the trimming or the forced-space behavior, at far lower cost than reviving the ACP+Codex live path.
  • Existing test that already covers this (if any): none. AcpSessionManager tests in manager.test.ts cover the surrounding state machine but not the chunk-progress contract.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

Parent-channel ACP background-task terminal summaries now render token-streamed text verbatim instead of with spurious inter-chunk spaces. No config or default changes. No change to summary length or truncation marker.

Diagram (if applicable)

Before:
chunks = ["디", "렉", "토", "리"]
  → trim each chunk          → ["디", "렉", "토", "리"]
  → join with forced space   → "디 렉 토 리"   ✗

After:
chunks = ["디", "렉", "토", "리"]
  → collapse internal \s runs only   → ["디", "렉", "토", "리"]
  → concatenate verbatim             → "디렉토리"     ✓

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

The change is a string-handling fix in a pure helper that processes already-received progress chunks. It cannot widen any trust boundary.

Repro + Verification

Environment

  • OS: Ubuntu 24.04.4 LTS (x86_64)
  • Runtime/container: Node 22.22.2, npm-global OpenClaw 2026.4.21 install (live env), upstream main at cbaf999bd2 for the patch (2026.5.5)
  • Model/provider: gpt-5.3-codex via Codex CLI 0.121.0, ChatGPT Plus auth
  • Integration/channel (if any): Discord, parent agent (Hermes / openai-codex/gpt-5.4) → ACP acpx → Codex child
  • Relevant config (redacted): acp.backend: "acpx", acp.defaultAgent: "codex", acp.allowedAgents: ["codex"], acp.dispatch.enabled: true, ~/.codex/config.toml with model = "gpt-5.3-codex"

Steps

  1. Trigger a sessions_spawn(runtime: "acp", agentId: "codex", task: "<Korean prompt asking Codex to print the absolute path of its current working directory>") from the orchestrator agent.
  2. Wait for the background-task done announce in the parent channel.
  3. Compare the rendered text against the actual Codex response in the child session log.

Expected

  • Announce text matches Codex's underlying response verbatim (Korean syllables joined, path separators preserved).

Actual (with this patch applied)

  • Announce text matches Codex's underlying response verbatim. Reproduced 1/1 immediately after applying the patch and restarting the gateway.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

The before/after announce text is included verbatim in the Real behavior proof section above. Unit-test output before the source change would fail at expect(summary).toBe("디렉토리") (actual "디 렉 토 리"); after the change all 10 cases pass.

Human Verification (required)

  • Verified scenarios:
    • Korean prompt to Codex via ACP, before and after patch, real Discord channel.
    • Mixed Korean + English path prompt to Codex, after patch — path separators preserved, Korean joined correctly.
    • Local unit tests on the patched helper for CJK one-char-per-chunk, path mid-segment, CamelCase mid-word, leading-/trailing-space chunks, whitespace-run chunks, empty/non-string chunks, length cap (240).
  • Edge cases checked: empty chunk, null/undefined chunk (cast through unknown), pure-whitespace chunks, single-character chunks, oversized chunk that triggers the cap and truncation.
  • What you did not verify: non-Codex ACP runtimes (Claude Code etc.) end-to-end; native Windows or macOS gateway runs (the helper is platform-independent so this should not matter); full pnpm test / pnpm test:extensions suite (ran pnpm check:changed instead, which is the smart-gate equivalent for the changed paths).

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

(No conversations yet at PR open time; will keep these in sync as bot reviews land.)

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A.

Risks and Mitigations

  • Risk: a runtime that previously relied on the trim+force-space behavior to compress whitespace-only chunks into clean prose might now show extra leading whitespace if its first chunk is whitespace.
    • Mitigation: any leading whitespace from a stream's first chunk is still bounded by the existing length cap, and the downstream resolveBackgroundTaskTerminalResult already does its own .trim() on the final summary before producing user-visible text, so this surface is normalized at the edge. Internal multi-line chunks are still collapsed to a single space line within the helper.

Scope vs #74070 / PR #74103

Independent. PR #74103 raises the cap and surfaces progress as terminalSummary on success — both useful — but keeps the same trim-and-force-space pattern in appendBackgroundTaskProgressSummary, so the rendered output would still show 디 렉 토 리 even after #74103 lands. This PR is orthogonal and safe to merge in either order; if both land, the resulting helper retains both improvements (visible inter-word boundaries from this PR, larger cap and success-path terminal summary from #74103).

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/acp/control-plane/manager.background-task-progress.test.ts (added, +85/-0)
  • src/acp/control-plane/manager.core.ts (modified, +7/-4)

PR #78383: Fix ACP streamed progress summary spacing

Description (problem / solution / changelog)

Summary

  • Preserve ACP background-task progress chunk boundaries instead of trimming each streamed delta and inserting a synthetic space.
  • Add regression coverage for split Korean/path chunks and for split permission-denied progress that still resolves to a blocked terminal summary.
  • Add the required unreleased changelog entry for #78312.

Fixes #78312.

Verification

  • pnpm test src/acp/control-plane/manager.test.ts
  • pnpm exec oxfmt --check --threads=1 src/acp/control-plane/manager.core.ts src/acp/control-plane/manager.test.ts CHANGELOG.md
  • git diff --check origin/main...HEAD
  • Deterministic helper-level repro: old join produced 현재 작업 디 렉토 리는 /home/ by kim 0119/ .open claw/ workspace 입니다; fixed join produced 현재 작업 디렉토리는 /home/bykim0119/.openclaw/workspace 입니다.

Notes

  • Crabbox/Blacksmith Testbox focused validation was attempted, but the lease stayed queued for several minutes and was stopped cleanly before PR creation.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/acp/control-plane/manager.core.ts (modified, +6/-2)
  • src/acp/control-plane/manager.test.ts (modified, +110/-1)

Code Example

## Observed output (live, Codex via ACP, Korean prompt asking for the workspace path)

Discord (broken):  현재 작업 디 렉 토 리 는 / home / by kim 0119 / . open claw / workspace 입니다
Expected:          현재 작업 디렉토리는 /home/bykim0119/.openclaw/workspace 입니다

The same Codex turn rendered directly through the Codex CLI (no ACP
background-task summary path) is correct, isolating the regression to
appendBackgroundTaskProgressSummary.


## Programmatic repro (deterministic, no ACP runtime needed)

import { appendBackgroundTaskProgressSummary } from "./src/acp/control-plane/manager.core.js";

function run(chunks) {
  let summary = "";
  for (const c of chunks) summary = appendBackgroundTaskProgressSummary(summary, c);
  return summary;
}

// CJK token-streamed
run(["현재", "작업", "디", "렉토", "리"]);
// Actual:   "현재 작업 디 렉토 리"
// Expected: "현재작업디렉토리"

// English path split mid-segment
run(["/home/", "user/", "file.", "txt"]);
// Actual:   "/home/ user/ file. txt"
// Expected: "/home/user/file.txt"

// English identifier split mid-word
run(["unbeliev", "able"]);
// Actual:   "unbeliev able"
// Expected: "unbelievable"

// English prose (incidentally fine because BPE leading-space tokens
// happen to align with the forced-space behavior)
run(["hello", " world"]);  // "hello world"  ✓
run(["hello ", "world"]);  // "hello world"  ✓


## Current code (src/acp/control-plane/manager.core.ts, ~L99)

function appendBackgroundTaskProgressSummary(current: string, chunk: string): string {
  const normalizedChunk = normalizeText(chunk)?.replace(/\s+/g, " ");
  if (!normalizedChunk) {
    return current;
  }
  const combined = current ? `${current} ${normalizedChunk}` : normalizedChunk;
  if (combined.length <= ACP_BACKGROUND_TASK_PROGRESS_MAX_LENGTH) {
    return combined;
  }
  return `${combined.slice(0, ACP_BACKGROUND_TASK_PROGRESS_MAX_LENGTH - 1)}`;
}
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

appendBackgroundTaskProgressSummary in src/acp/control-plane/manager.core.ts trims every streamed chunk and forces a join space, so any token-streamed text whose chunk boundaries fall inside a word loses those boundaries — 디렉토리 is rendered as 디 렉 토 리, and an English path like /home/bykim0119/.openclaw/workspace is rendered as / home / by kim 0119 / . open claw / workspace. The bug is most visible for CJK and for paths/URLs/identifiers, but it applies to any chunked stream where a chunk boundary is mid-word.

Steps to reproduce

  1. Configure ACP with acp.backend: "acpx", defaultAgent: "codex", dispatch.enabled: true.
  2. Have the orchestrator agent issue sessions_spawn(runtime: "acp", agentId: "codex", task: "<a Korean prompt that asks Codex to print an absolute path or any sentence>").
  3. Wait for the background task to complete; observe the auto-announced terminal summary in the parent channel.
  4. The Korean text in the announce is broken across characters with extra spaces inserted at every chunk boundary.

Expected behavior

The streamed progress summary preserves the original word boundaries: token chunks are concatenated as-is, so ["디", "렉토", "리"] produces 디렉토리, and chunk-boundary whitespace (e.g. ["hello", " world"] or ["hello ", "world"]) is preserved verbatim as the inter-word boundary.

Actual behavior

normalizeText(chunk) (= normalizeOptionalString in src/shared/string-coerce.ts) calls value.trim(), stripping the leading/trailing whitespace that carries the inter-chunk boundary signal. The ${current} ${normalizedChunk} template then forces a single space at every join, which is the wrong default for token-streamed output (especially CJK, where chunks routinely split mid-word).

OpenClaw version

2026.4.21 (live verification) — code path unchanged on main at 2026.5.5

Operating system

Ubuntu 24.04.4 LTS

Install method

npm global

Model

gpt-5.3-codex (Codex CLI 0.121.0)

Provider / routing chain

openclaw -> ACP (acpx) -> codex CLI -> ChatGPT (gpt-5.3-codex)

Additional provider/model setup details

No response

Logs, screenshots, and evidence

## Observed output (live, Codex via ACP, Korean prompt asking for the workspace path)

Discord (broken):  현재 작업 디 렉 토 리 는 / home / by kim 0119 / . open claw / workspace 입니다
Expected:          현재 작업 디렉토리는 /home/bykim0119/.openclaw/workspace 입니다

The same Codex turn rendered directly through the Codex CLI (no ACP
background-task summary path) is correct, isolating the regression to
appendBackgroundTaskProgressSummary.


## Programmatic repro (deterministic, no ACP runtime needed)

import { appendBackgroundTaskProgressSummary } from "./src/acp/control-plane/manager.core.js";

function run(chunks) {
  let summary = "";
  for (const c of chunks) summary = appendBackgroundTaskProgressSummary(summary, c);
  return summary;
}

// CJK token-streamed
run(["현재", "작업", "디", "렉토", "리"]);
// Actual:   "현재 작업 디 렉토 리"
// Expected: "현재작업디렉토리"

// English path split mid-segment
run(["/home/", "user/", "file.", "txt"]);
// Actual:   "/home/ user/ file. txt"
// Expected: "/home/user/file.txt"

// English identifier split mid-word
run(["unbeliev", "able"]);
// Actual:   "unbeliev able"
// Expected: "unbelievable"

// English prose (incidentally fine because BPE leading-space tokens
// happen to align with the forced-space behavior)
run(["hello", " world"]);  // "hello world"run(["hello ", "world"]);  // "hello world"

## Current code (src/acp/control-plane/manager.core.ts, ~L99)

function appendBackgroundTaskProgressSummary(current: string, chunk: string): string {
  const normalizedChunk = normalizeText(chunk)?.replace(/\s+/g, " ");
  if (!normalizedChunk) {
    return current;
  }
  const combined = current ? `${current} ${normalizedChunk}` : normalizedChunk;
  if (combined.length <= ACP_BACKGROUND_TASK_PROGRESS_MAX_LENGTH) {
    return combined;
  }
  return `${combined.slice(0, ACP_BACKGROUND_TASK_PROGRESS_MAX_LENGTH - 1)}`;
}

Impact and severity

  • Affected: ACP background-task users whose model output streams chunks that cut mid-word. Universal for CJK output, paths, URLs, and code identifiers; mostly invisible for plain English prose because BPE leading-space tokens incidentally align with the forced-space behavior.
  • Severity: Annoying / blocks readability of agent summaries. Announce text becomes unreadable, but underlying agent output, persisted transcripts, and downstream tool calls are intact — no data loss or workflow block.
  • Frequency: Deterministic at the helper level (always reproducible from a fixed chunk sequence). Always reproducible end-to-end on Korean Codex output via ACP, including the path portion.
  • Consequence: Parent-channel terminal summaries are unusable for non-English ACP workloads and for any output that mixes paths, URLs, or CamelCase / snake_case identifiers. Users who rely on the announced summary as the primary signal of background-task output (e.g. on mobile Discord) lose that signal and must drop into the child session to read the real result.

Additional information

Scope vs #74070 / #74103. Independent. PR #74103 raises the progress cap and surfaces the progress as terminalSummary on success — both useful — but its appendBackgroundTaskProgressSummary keeps the same trim-and-force-space pattern, so the rendered output would still show 디 렉 토 리 even after #74103 lands.

Why English prose looks fine. BPE-style tokenizers (used by GPT/Codex) prefix most word tokens with a leading space (" world", " the"), which happens to align with the forced-space behavior here. CJK output, paths, URLs, and CamelCase / snake_case identifiers do not have that leading-space alignment and break visibly at every chunk boundary.

Fix PR. A PR is being prepared that drops the normalizeText (trim) call on the chunk and the forced join space, while still collapsing internal whitespace runs (newlines, tabs, multi-space) to a single space and keeping the existing length cap. Unit tests cover the CJK case, leading-/trailing-space chunks, newline/tab collapse, length cap, and empty-chunk no-op.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The streamed progress summary preserves the original word boundaries: token chunks are concatenated as-is, so ["디", "렉토", "리"] produces 디렉토리, and chunk-boundary whitespace (e.g. ["hello", " world"] or ["hello ", "world"]) is preserved verbatim as the inter-word boundary.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: ACP background-task summary corrupts token-streamed text (CJK breaks into single chars, paths split with spaces) [2 pull requests, 1 comments, 2 participants]