@@ -15,37 +15,25 @@ import {
1515} from "../../usage/token-usage" ;
1616import { isObjectRecord , type JsonObject } from "../../utils/object" ;
1717
18- const CODE_REFERENCES_MARKER = "# Code References" ;
1918const OPENCODE_IDENTITY_MARKER =
2019 "You are OpenCode, the best coding agent on the planet." ;
2120
22- const formatXmlTag = ( name : string ) : string => {
23- const words = name . replaceAll ( / [ _ - ] + / g, " " ) ;
24- return `${ words [ 0 ] ?. toUpperCase ( ) ?? "" } ${ words . slice ( 1 ) } :` ;
25- } ;
26-
27- const flattenXmlTags = ( text : string ) : string =>
28- text
29- . replace ( / < \/ ( [ a - z ] [ a - z 0 - 9 _ - ] * ) > / gi, "" )
30- . replace (
31- / < ( [ a - z ] [ a - z 0 - 9 _ - ] * ) > / gi,
32- ( _ , name : string ) => `${ formatXmlTag ( name ) } \n`
33- ) ;
34-
35- // Anthropic OAuth sessions appear to reject XML-like tags in the OpenCode
36- // tail. Keep the tail in system[] but flatten those wrappers.
37- const sanitizeClaudeSystemText = ( text : string ) : string => {
38- const start = text . indexOf ( OPENCODE_IDENTITY_MARKER ) ;
39- if ( start === - 1 ) {
40- return text ;
41- }
42-
43- const end = text . indexOf ( CODE_REFERENCES_MARKER , start ) ;
44- if ( end === - 1 ) {
21+ // Anthropic OAuth sessions reject parts of the OpenCode system prompt. Keep
22+ // the prompt in system[] while flattening XML-like tags and stripping the
23+ // feedback URL that triggers the block.
24+ // https://github.com/anomalyco/opencode/blob/d848c9b6a32f408e8b9bf6448b83af05629454d0/packages/opencode/src/session/prompt/anthropic.txt
25+ // https://github.com/anomalyco/opencode/blob/d848c9b6a32f408e8b9bf6448b83af05629454d0/packages/opencode/src/session/system.ts#L32-L72
26+ const sanitizeOpenCodeSystem = ( text : string ) : string => {
27+ if ( ! text . includes ( OPENCODE_IDENTITY_MARKER ) ) {
4528 return text ;
4629 }
4730
48- return `${ text . slice ( 0 , start ) } ${ flattenXmlTags ( text . slice ( end ) ) } ` ;
31+ return text
32+ . replace ( / h t t p s : \/ \/ g i t h u b \. c o m \/ a n o m a l y c o \/ o p e n c o d e / gi, "" )
33+ . replace ( / < e n v > / gi, "Environment\n" )
34+ . replace ( / < d i r e c t o r i e s > / gi, "Directories\n" )
35+ . replace ( / < a v a i l a b l e _ s k i l l s > / gi, "Available skills\n" )
36+ . replace ( / < \/ ? [ a - z ] [ a - z 0 - 9 _ - ] * > / gi, "" ) ;
4937} ;
5038
5139// Request: prefix tool names so they match Claude Code's expected format.
@@ -72,7 +60,7 @@ const transformClaudeRequestPayload = (
7260 const transformed : JsonObject = { ...payload } ;
7361
7462 if ( typeof transformed . system === "string" ) {
75- const sanitizedSystem = sanitizeClaudeSystemText ( transformed . system ) ;
63+ const sanitizedSystem = sanitizeOpenCodeSystem ( transformed . system ) ;
7664 const systemBlocks : Array < { type : string ; text : string } > = [
7765 { type : "text" , text : systemIdentity } ,
7866 ] ;
@@ -90,7 +78,7 @@ const transformClaudeRequestPayload = (
9078 ) {
9179 systemBlocks . push ( {
9280 ...block ,
93- text : sanitizeClaudeSystemText ( block . text ) ,
81+ text : sanitizeOpenCodeSystem ( block . text ) ,
9482 } ) ;
9583 continue ;
9684 }
0 commit comments