@@ -14,6 +14,8 @@ import * as FileSystem from "effect/FileSystem";
1414import * as Path from "effect/Path" ;
1515import * as Fiber from "effect/Fiber" ;
1616import * as Layer from "effect/Layer" ;
17+ import * as Sink from "effect/Sink" ;
18+ import * as Stream from "effect/Stream" ;
1719import * as Schema from "effect/Schema" ;
1820import * as HttpClient from "effect/http/HttpClient" ;
1921import * as HttpClientResponse from "effect/http/HttpClientResponse" ;
@@ -823,6 +825,90 @@ describe("AcpRegistrySupport", () => {
823825 ) ;
824826 } ) ;
825827
828+ it . effect ( "prepares an x64 ZIP fallback on Windows ARM when PATH tar cannot read ZIP" , ( ) => {
829+ const downloadUrl = "https://registry.test/agent-windows-x64.zip" ;
830+ const agent = makeAgent ( {
831+ binary : { "windows-x86_64" : { archive : downloadUrl , cmd : "./agent.exe" } } ,
832+ npx :
{ package :
"@example/[email protected] " } , 833+ } ) ;
834+ return Effect . gen ( function * ( ) {
835+ const fileSystem = yield * FileSystem . FileSystem ;
836+ const path = yield * Path . Path ;
837+ const cacheDir = yield * fileSystem . makeTempDirectoryScoped ( { prefix : "t3-acp-arm-zip-" } ) ;
838+ const commands : Array < string > = [ ] ;
839+ const spawner = ChildProcessSpawner . make ( ( command ) =>
840+ Effect . gen ( function * ( ) {
841+ if ( command . _tag !== "StandardCommand" ) return yield * Effect . die ( "Unexpected pipeline" ) ;
842+ commands . push ( command . command ) ;
843+ // Simulate Git's GNU tar rejecting ZIP and System32 bsdtar listing/extracting it.
844+ const supportsZip = command . command === "C:\\Windows\\System32\\tar.exe" ;
845+ if ( supportsZip && command . args [ 0 ] === "-xf" ) {
846+ const outputDirectory = command . args [ 3 ] ;
847+ if ( ! outputDirectory ) return yield * Effect . die ( "Missing extraction directory" ) ;
848+ yield * fileSystem . writeFileString ( path . join ( outputDirectory , "agent.exe" ) , "fixture" ) ;
849+ }
850+ return ChildProcessSpawner . makeHandle ( {
851+ pid : ChildProcessSpawner . ProcessId ( 1 ) ,
852+ exitCode : Effect . succeed ( ChildProcessSpawner . ExitCode ( supportsZip ? 0 : 1 ) ) ,
853+ isRunning : Effect . succeed ( false ) ,
854+ kill : ( ) => Effect . void ,
855+ unref : Effect . succeed ( Effect . void ) ,
856+ stdin : Sink . drain ,
857+ stdout : Stream . make ( new TextEncoder ( ) . encode ( supportsZip ? "agent.exe\r\n" : "" ) ) ,
858+ stderr : Stream . make (
859+ new TextEncoder ( ) . encode ( supportsZip ? "" : "GNU tar cannot read ZIP" ) ,
860+ ) ,
861+ all : Stream . empty ,
862+ getInputFd : ( ) => Sink . drain ,
863+ getOutputFd : ( ) => Stream . empty ,
864+ } ) ;
865+ } ) . pipe ( Effect . orDie ) ,
866+ ) ;
867+ const resolver = yield * AcpRegistrySupport . makeAcpRegistryCatalog ( {
868+ cacheDir,
869+ toolsDir : path . join ( cacheDir , "tools" ) ,
870+ registryUrl,
871+ } ) . pipe (
872+ Effect . provideService ( ChildProcessSpawner . ChildProcessSpawner , spawner ) ,
873+ Effect . provideService ( HostProcess . Platform , "win32" ) ,
874+ Effect . provideService ( HostProcess . Architecture , "arm64" ) ,
875+ Effect . provideService ( HostProcess . Environment , {
876+ SystemRoot : "C:\\Windows" ,
877+ PATH : "C:\\Program Files\\Git\\usr\\bin;C:\\Windows\\System32" ,
878+ } ) ,
879+ Effect . provideService ( SpawnExecutableResolution , ( command ) =>
880+ command === "tar" ? "C:\\Program Files\\Git\\usr\\bin\\tar.exe" : command ,
881+ ) ,
882+ ) ;
883+ yield * resolver . prepare ( { agentId : agent . id } ) ;
884+ const resolved = yield * resolver . resolve ( settings ( ) , "/workspace" , { } ) ;
885+ expect ( resolved . spawn . command ) . toBe (
886+ yield * fileSystem . realPath (
887+ path . join ( cacheDir , "tools" , agent . id , agent . version , "windows-x86_64" , "agent.exe" ) ,
888+ ) ,
889+ ) ;
890+ expect ( yield * fileSystem . readFileString ( resolved . spawn . command ) ) . toBe ( "fixture" ) ;
891+ expect ( commands ) . toEqual ( [
892+ "C:\\Windows\\System32\\tar.exe" ,
893+ "C:\\Windows\\System32\\tar.exe" ,
894+ ] ) ;
895+ } ) . pipe (
896+ Effect . scoped ,
897+ Effect . provide (
898+ layerResolver ( ( request ) =>
899+ Effect . succeed (
900+ HttpClientResponse . fromWeb (
901+ request ,
902+ request . url === registryUrl
903+ ? new Response ( makeRegistry ( agent ) )
904+ : new Response ( "ZIP fixture" ) ,
905+ ) ,
906+ ) ,
907+ ) ,
908+ ) ,
909+ ) ;
910+ } ) ;
911+
826912 it . effect ( "searches compatible agents with deterministic ranking and bounded metadata" , ( ) => {
827913 const exact = {
828914 ...
makeAgent ( { npx :
{ package :
"@example/[email protected] " } } ) ,
0 commit comments