11import assert from "node:assert/strict"
22import { describe , it } from "node:test"
33import {
4+ parseBlockedReplacementsEnv ,
45 repairToolPairs ,
56 stripToolPrefix ,
67 transformBody ,
@@ -35,9 +36,14 @@ describe("transforms", () => {
3536 assert . equal ( parsed . messages [ 0 ] . content [ 0 ] . name , "mcp_Lookup" )
3637 } )
3738
38- it ( "transformBody scrubs blocked URL from system text in-place" , ( ) => {
39+ it ( "transformBody scrubs blocked URL from system text in-place with grammatical replacement " , ( ) => {
3940 const input = JSON . stringify ( {
40- system : [ { type : "text" , text : "Report at https://github.com/anomalyco/opencode for bugs" } ] ,
41+ system : [
42+ {
43+ type : "text" ,
44+ text : "Report at https://github.com/anomalyco/opencode for bugs" ,
45+ } ,
46+ ] ,
4147 tools : [ { name : "search" } ] ,
4248 messages : [
4349 { role : "user" , content : [ { type : "tool_use" , name : "lookup" } ] } ,
@@ -54,14 +60,87 @@ describe("transforms", () => {
5460 } >
5561 }
5662
57- // blocked URL scrubbed, entry stays in system[]
63+ // blocked URL scrubbed, entry stays in system[], surrounding prose intact.
5864 assert . equal ( parsed . system . length , 2 ) // billing + scrubbed entry
5965 assert . ok ( ! parsed . system [ 1 ] . text . includes ( "anomalyco" ) )
60- assert . ok ( parsed . system [ 1 ] . text . includes ( "Report at" ) )
66+ assert . ok ( ! parsed . system [ 1 ] . text . includes ( "github.com/anomalyco" ) )
67+ // Replacement preserves grammar — no double spaces, no dangling phrases.
68+ assert . equal (
69+ parsed . system [ 1 ] . text ,
70+ "Report at https://opencode.ai for bugs" ,
71+ )
6172 assert . equal ( parsed . tools [ 0 ] . name , "mcp_Search" )
6273 assert . equal ( parsed . messages [ 0 ] . content [ 0 ] . name , "mcp_Lookup" )
6374 } )
6475
76+ it ( "transformBody scrubs blocked URL embedded in a realistic concatenated system prompt" , ( ) => {
77+ // Mirrors how OpenCode actually emits system[]: identity prefix, then
78+ // a single concatenated block containing agent prompt + env + AGENTS
79+ // + skills, with the blocked URL appearing once inside the body.
80+ const identity = "You are Claude Code, Anthropic's official CLI for Claude."
81+ const concatenated = [
82+ "You are OpenCode, the best coding agent on the planet." ,
83+ "Report bugs at https://github.com/anomalyco/opencode." ,
84+ "Working directory: /Users/test/dev/project" ,
85+ "## AGENTS.md" ,
86+ "Use TDD when writing new features." ,
87+ ] . join ( "\n\n" )
88+
89+ const input = JSON . stringify ( {
90+ system : [
91+ { type : "text" , text : identity } ,
92+ { type : "text" , text : concatenated } ,
93+ ] ,
94+ messages : [ { role : "user" , content : "hello" } ] ,
95+ } )
96+
97+ const output = transformBody ( input )
98+ const parsed = JSON . parse ( output as string ) as {
99+ system : Array < { text : string } >
100+ messages : Array < { content : string | Array < { text ?: string } > } >
101+ }
102+
103+ // billing + identity + concatenated body — body stays in system[].
104+ assert . equal ( parsed . system . length , 3 )
105+ assert . ok ( parsed . system [ 0 ] . text . startsWith ( "x-anthropic-billing-header:" ) )
106+ assert . equal ( parsed . system [ 1 ] . text , identity )
107+ // Body retained, blocked URL scrubbed, all other content intact.
108+ assert . ok ( ! parsed . system [ 2 ] . text . includes ( "github.com/anomalyco" ) )
109+ assert . ok ( parsed . system [ 2 ] . text . includes ( "opencode.ai" ) )
110+ assert . ok ( parsed . system [ 2 ] . text . includes ( "Working directory" ) )
111+ assert . ok ( parsed . system [ 2 ] . text . includes ( "AGENTS.md" ) )
112+ assert . ok ( parsed . system [ 2 ] . text . includes ( "Use TDD" ) )
113+ // User message untouched (no relocation).
114+ assert . equal ( parsed . messages [ 0 ] . content , "hello" )
115+ } )
116+
117+ it ( "parseBlockedReplacementsEnv parses comma-separated patterns with optional replacements" , ( ) => {
118+ assert . deepEqual ( parseBlockedReplacementsEnv ( undefined ) , [ ] )
119+ assert . deepEqual ( parseBlockedReplacementsEnv ( "" ) , [ ] )
120+ assert . deepEqual ( parseBlockedReplacementsEnv ( " " ) , [ ] )
121+
122+ // Bare patterns scrub to empty string.
123+ assert . deepEqual ( parseBlockedReplacementsEnv ( "foo.example,bar.example" ) , [
124+ { pattern : "foo.example" , replacement : "" } ,
125+ { pattern : "bar.example" , replacement : "" } ,
126+ ] )
127+
128+ // pattern=replacement form.
129+ assert . deepEqual (
130+ parseBlockedReplacementsEnv ( "foo.example=foo.ok,bar.example" ) ,
131+ [
132+ { pattern : "foo.example" , replacement : "foo.ok" } ,
133+ { pattern : "bar.example" , replacement : "" } ,
134+ ] ,
135+ )
136+
137+ // Whitespace around tokens is trimmed; empty patterns dropped.
138+ assert . deepEqual ( parseBlockedReplacementsEnv ( " a = b , , c=d , =orphan " ) , [
139+ { pattern : "a" , replacement : "b" } ,
140+ { pattern : "c" , replacement : "d" } ,
141+ ] )
142+ } )
143+
65144 it ( "transformBody keeps safe non-core system text in system[]" , ( ) => {
66145 const input = JSON . stringify ( {
67146 system : [
@@ -82,7 +161,10 @@ describe("transforms", () => {
82161
83162 // Safe text stays in system[]
84163 assert . equal ( parsed . system . length , 2 ) // billing + safe text
85- assert . equal ( parsed . system [ 1 ] . text , "Use opencode-claude-auth plugin instructions as-is." )
164+ assert . equal (
165+ parsed . system [ 1 ] . text ,
166+ "Use opencode-claude-auth plugin instructions as-is." ,
167+ )
86168 } )
87169
88170 it ( "transformBody keeps safe URL/path system text in system[]" , ( ) => {
@@ -105,7 +187,10 @@ describe("transforms", () => {
105187
106188 // Safe URLs stay in system[]
107189 assert . equal ( parsed . system . length , 2 )
108- assert . equal ( parsed . system [ 1 ] . text , "OpenCode docs: https://example.com/opencode/docs and path /var/opencode/bin" )
190+ assert . equal (
191+ parsed . system [ 1 ] . text ,
192+ "OpenCode docs: https://example.com/opencode/docs and path /var/opencode/bin" ,
193+ )
109194 } )
110195
111196 it ( "transformBody injects billing header as system[0] with computed cch" , ( ) => {
0 commit comments