@@ -231,13 +231,46 @@ function withFakeLlm<A, E, R>(backend: Backend, run: (input: LlmProjectFixture)
231231 } ) . pipe ( Effect . provide ( TestLLMServer . layer ) )
232232}
233233
234+ function withFakeLlmProject < A , E , R > (
235+ backend : Backend ,
236+ options : { setup ?: ( dir : string ) => Effect . Effect < void > } ,
237+ run : ( input : LlmProjectFixture ) => Effect . Effect < A , E , R > ,
238+ ) {
239+ return Effect . gen ( function * ( ) {
240+ const llm = yield * TestLLMServer
241+ return yield * withProject (
242+ backend ,
243+ {
244+ config : providerConfig ( llm . url ) ,
245+ setup : options . setup ,
246+ } ,
247+ ( input ) => run ( { ...input , llm } ) ,
248+ )
249+ } ) . pipe ( Effect . provide ( TestLLMServer . layer ) )
250+ }
251+
234252function writeStandardFiles ( dir : string ) {
235253 return Effect . all ( [
236254 call ( ( ) => Bun . write ( path . join ( dir , "hello.txt" ) , "hello" ) ) ,
237255 call ( ( ) => Bun . write ( path . join ( dir , "needle.ts" ) , "export const needle = 'sdk-parity'\n" ) ) ,
238256 ] ) . pipe ( Effect . asVoid )
239257}
240258
259+ function writeProjectSkill ( dir : string ) {
260+ return call ( ( ) =>
261+ Bun . write (
262+ path . join ( dir , ".opencode" , "skills" , "project-rest-skill" , "SKILL.md" ) ,
263+ `---
264+ name: project-rest-skill
265+ description: A project skill visible to REST API prompts.
266+ ---
267+
268+ # Project REST Skill
269+ ` ,
270+ ) ,
271+ ) . pipe ( Effect . asVoid )
272+ }
273+
241274function seedMessage ( directory : string , sessionID : string ) {
242275 const id = SessionID . make ( sessionID )
243276 return call (
@@ -647,6 +680,36 @@ describe("HttpApi SDK", () => {
647680 ) ,
648681 )
649682
683+ httpapi (
684+ "includes project skills in REST API async prompt context" ,
685+ withFakeLlmProject ( "httpapi" , { setup : writeProjectSkill } , ( { sdk, llm } ) =>
686+ Effect . gen ( function * ( ) {
687+ yield * llm . text ( "skill context ok" , { usage : { input : 11 , output : 7 } } )
688+ const session = yield * capture ( ( ) =>
689+ sdk . session . create ( {
690+ title : "project skill prompt" ,
691+ permission : [ { permission : "*" , pattern : "*" , action : "allow" } ] ,
692+ } ) ,
693+ )
694+ const sessionID = String ( record ( session . data ) . id )
695+ const prompt = yield * capture ( ( ) =>
696+ sdk . session . promptAsync ( {
697+ sessionID,
698+ agent : "build" ,
699+ model : { providerID : "test" , modelID : "test-model" } ,
700+ parts : [ { type : "text" , text : "hello skill context" } ] ,
701+ } ) ,
702+ )
703+ yield * llm . wait ( 1 )
704+ const inputs = yield * llm . inputs
705+
706+ expect ( session . status ) . toBe ( 200 )
707+ expect ( prompt . status ) . toBe ( 204 )
708+ expect ( JSON . stringify ( inputs [ 0 ] ) ) . toContain ( "project-rest-skill" )
709+ } ) ,
710+ ) ,
711+ )
712+
650713 parity ( "matches generated SDK TUI validation and command routes across backends" , ( backend ) =>
651714 withStandardProject ( backend , ( { sdk } ) =>
652715 Effect . gen ( function * ( ) {
0 commit comments