@@ -8,14 +8,15 @@ import { ClaudeProvider } from "./provider.js"
88
99const KINDS = [ "context" , "generate" , "compaction" ] as const
1010
11- const InstructionsMetadata = Schema . Struct ( {
11+ const PartMetadata = Schema . Struct ( {
1212 experimental : Schema . Struct ( {
13- instructions : Schema . Array ( Schema . Struct ( { key : Schema . String , text : Schema . String } ) ) ,
13+ key : Schema . optional ( Schema . String ) ,
14+ instructions : Schema . optional ( Schema . Array ( Schema . Struct ( { key : Schema . String , text : Schema . String } ) ) ) ,
1415 } ) ,
1516} )
1617
17- // Claude Code writes its own date and environment, so OpenCode's would repeat them.
18- const SUPPLIED_BY_CLAUDE = new Set ( [ "core/date" , "core/environment" ] )
18+ // Claude Code writes its own base prompt, model identity, date and environment, so OpenCode's would repeat them.
19+ const SUPPLIED_BY_CLAUDE = new Set ( [ "core/prompt" , "core/identity" , "core/ date", "core/environment" ] )
1920
2021export const register = Effect . fn ( "ClaudeInstructions.register" ) ( function * ( ctx : Context ) {
2122 yield * Effect . forEach (
@@ -51,19 +52,15 @@ export const register = Effect.fn("ClaudeInstructions.register")(function* (ctx:
5152 )
5253} )
5354
54- // The first part is OpenCode's own prompt, which Claude Code's prompt replaces .
55+ // OpenCode tags the parts Claude Code supplies itself, so plugins may add parts anywhere in the array .
5556function instructions ( system : ReadonlyArray < SystemPart > ) {
56- const texts : string [ ] = [ ]
57- for ( const part of system . slice ( 1 ) ) {
58- const metadata = Schema . decodeUnknownOption ( InstructionsMetadata ) ( part . metadata )
59- if ( Option . isNone ( metadata ) ) {
60- texts . push ( part . text )
61- continue
62- }
63- for ( const source of metadata . value . experimental . instructions ) {
64- if ( SUPPLIED_BY_CLAUDE . has ( source . key ) ) continue
65- texts . push ( source . text )
66- }
67- }
68- return texts . join ( "\n\n" )
57+ return system
58+ . flatMap ( ( part ) => {
59+ const metadata = Option . getOrUndefined ( Schema . decodeUnknownOption ( PartMetadata ) ( part . metadata ) ) ?. experimental
60+ if ( metadata ?. key && SUPPLIED_BY_CLAUDE . has ( metadata . key ) ) return [ ]
61+ if ( ! metadata ?. instructions ) return [ part . text ]
62+ return metadata . instructions . filter ( ( source ) => ! SUPPLIED_BY_CLAUDE . has ( source . key ) ) . map ( ( source ) => source . text )
63+ } )
64+ . filter ( Boolean )
65+ . join ( "\n\n" )
6966}
0 commit comments